From 8c1e0bdc781596973b86a592fe76704eeb49c127 Mon Sep 17 00:00:00 2001 From: "jke@jke_thinkpad_t460" <johannes.joachim.keller@rwth-aachen.de> Date: Wed, 25 Mar 2020 18:34:23 +0100 Subject: [PATCH] SHEMAT-Suite: Version 9.00 --- .gitignore | 6 + .gitlab/issue_templates/Error.md | 23 + CMakeLists.txt | 93 + LICENSE.md | 21 + cmake/AD.cmake | 148 ++ cmake/Dependencies.cmake | 76 + cmake/Flags.cmake | 60 + cmake/Options.cmake | 73 + cmake/Packages.cmake | 41 + cmake/Sources.cmake | 137 ++ doc/Doxyfile | 2327 +++++++++++++++++++++++++ doc/doc_image/cube.png | Bin 0 -> 4345 bytes forward/alloc_arrays.f90 | 423 +++++ forward/alloc_data.f90 | 87 + forward/arrays.f90 | 738 ++++++++ forward/bhpr.f90 | 149 ++ forward/check_change.f90 | 134 ++ forward/check_props.f90 | 76 + forward/check_units.f90 | 161 ++ forward/conc/calc_conc.f90 | 107 ++ forward/conc/cfluxes.f90 | 338 ++++ forward/conc/neumann_conc.f90 | 215 +++ forward/conc/peclet_conc.f90 | 226 +++ forward/conc/set_cbc.f90 | 226 +++ forward/conc/set_ccoef.f90 | 275 +++ forward/conc/set_cq.f90 | 66 + forward/converged.f90 | 157 ++ forward/courant.f90 | 200 +++ forward/ctrlut/decntrl3.f90 | 45 + forward/ctrlut/decntrl4.f90 | 49 + forward/ctrlut/encntrl3.f90 | 35 + forward/ctrlut/encntrl4.f90 | 36 + forward/ctrlut/ijk_m.f90 | 91 + forward/ctrlut/m_ijk.f90 | 36 + forward/dealloc_arrays.f90 | 245 +++ forward/deltat.f90 | 220 +++ forward/forward_init.f90 | 78 + forward/forward_iter.f90 | 210 +++ forward/forward_picard.f90 | 410 +++++ forward/forward_preparation.f90 | 70 + forward/forward_wrapper.f90 | 43 + forward/forward_write.f90 | 38 + forward/get_tpbcalbe.f90 | 73 + forward/head/calc_head.f90 | 95 + forward/head/hbuoy.f90 | 58 + forward/head/head2pres.f90 | 51 + forward/head/hfluxes.f90 | 328 ++++ forward/head/hstor.f90 | 44 + forward/head/neumann_head.f90 | 214 +++ forward/head/omp_head2pres.f90 | 83 + forward/head/set_hbc.f90 | 193 ++ forward/head/set_hcoef.f90 | 168 ++ forward/head/set_hq.f90 | 64 + forward/input/calc_deltatime.f90 | 152 ++ forward/input/read_array.f90 | 87 + forward/input/read_bc.f90 | 839 +++++++++ forward/input/read_check.f90 | 295 ++++ forward/input/read_control.f90 | 79 + forward/input/read_data.f90 | 656 +++++++ forward/input/read_model.f90 | 2028 +++++++++++++++++++++ forward/input/read_property.f90 | 76 + forward/input/read_split.f90 | 142 ++ forward/input/read_time.f90 | 612 +++++++ forward/mathfuncs/alfa.f90 | 48 + forward/mathfuncs/amean.f90 | 34 + forward/mathfuncs/interpolate_lin.f90 | 125 ++ forward/mathfuncs/interpolate_pol.f90 | 290 +++ forward/mathfuncs/mean3d.f90 | 51 + forward/mod_conc.f90 | 56 + forward/mod_data.f90 | 35 + forward/mod_flow.f90 | 102 ++ forward/mod_genrl.f90 | 253 +++ forward/mod_genrlc.f90 | 38 + forward/mod_linfos.f90 | 53 + forward/mod_temp.f90 | 34 + forward/mod_time.f90 | 172 ++ forward/model_init.f90 | 75 + forward/nlrelaxad.f90 | 68 + forward/no_ext_link.f90 | 208 +++ forward/old_restore.f90 | 73 + forward/old_save.f90 | 99 ++ forward/omp_bindtools.f90 | 262 +++ forward/omp_file_handler.f90 | 94 + forward/omp_libnuma.c | 50 + forward/omp_summe.f90 | 139 ++ forward/output/write_data.f90 | 113 ++ forward/output/write_dense3d.f90 | 90 + forward/output/write_logs.f90 | 98 ++ forward/output/write_monitor.f90 | 303 ++++ forward/output/write_outt.f90 | 102 ++ forward/output/write_status_log.f90 | 64 + forward/output/write_tecdiff.f90 | 137 ++ forward/output/write_tecplot.f90 | 737 ++++++++ forward/output/write_tecplotc.f90 | 149 ++ forward/output/write_text.f90 | 180 ++ forward/output/write_vtk.f90 | 307 ++++ forward/pres/calc_pres.f90 | 86 + forward/pres/neumann_pres.f90 | 203 +++ forward/pres/omp_pres2head.f90 | 60 + forward/pres/pbuoy.f90 | 105 ++ forward/pres/pfluxes.f90 | 365 ++++ forward/pres/pres2head.f90 | 51 + forward/pres/pstor.f90 | 44 + forward/pres/set_pbc.f90 | 218 +++ forward/pres/set_pcoef.f90 | 166 ++ forward/pres/set_pq.f90 | 64 + forward/save_data.f90 | 152 ++ forward/set_tsal.f90 | 82 + forward/set_var_deltat.f90 | 83 + forward/shemach/compress_file.f90 | 45 + forward/shemach/sys_cputime.f90 | 39 + forward/shemach/sys_mkdir.f90 | 40 + forward/stab_param.f90 | 50 + forward/static_relaxation.f90 | 70 + forward/strngut/beginlast.f90 | 45 + forward/strngut/cfirst.f90 | 42 + forward/strngut/chln.f90 | 60 + forward/strngut/clast.f90 | 41 + forward/strngut/found.f90 | 74 + forward/strngut/get_arg.f90 | 51 + forward/strngut/lblank.f90 | 41 + forward/strngut/locstr.f90 | 54 + forward/strngut/sfirst.f90 | 41 + forward/temp/calc_temp.f90 | 90 + forward/temp/neumann_temp.f90 | 203 +++ forward/temp/peclet_temp.f90 | 217 +++ forward/temp/set_tbc.f90 | 286 +++ forward/temp/set_tcoef.f90 | 274 +++ forward/temp/set_tq.f90 | 76 + forward/temp/tfluxes.f90 | 356 ++++ forward/test_opt.f90 | 100 ++ hdf5/close_hdf5.f90 | 56 + hdf5/closeopen_hdf5.f90 | 53 + hdf5/mod_hdf5_vars.f90 | 59 + hdf5/mod_input_file_parser_hdf5.f90 | 388 +++++ hdf5/open_hdf5.f90 | 60 + hdf5/read_hdf5.f90 | 117 ++ hdf5/read_hdf5_int.f90 | 127 ++ hdf5/test_hdf5.f90 | 32 + hdf5/write_all_hdf5.f90 | 698 ++++++++ props/bas/check_domain.f90 | 188 ++ props/bas/compf.f90 | 192 ++ props/bas/compm.f90 | 50 + props/bas/cpf.f90 | 198 +++ props/bas/disp.f90 | 50 + props/bas/kx.f90 | 54 + props/bas/ky.f90 | 54 + props/bas/kz.f90 | 50 + props/bas/lamf.f90 | 84 + props/bas/lamm.f90 | 128 ++ props/bas/lx.f90 | 98 ++ props/bas/ly.f90 | 98 ++ props/bas/lz.f90 | 98 ++ props/bas/por.f90 | 49 + props/bas/props_check.f90 | 63 + props/bas/props_end.f90 | 37 + props/bas/props_init.f90 | 41 + props/bas/qc.f90 | 55 + props/bas/qf.f90 | 50 + props/bas/qt.f90 | 51 + props/bas/rce.f90 | 84 + props/bas/read_props.f90 | 37 + props/bas/rhocf.f90 | 62 + props/bas/rhocm.f90 | 62 + props/bas/rhof.f90 | 169 ++ props/bas/visf.f90 | 167 ++ props/basc/check_domain.f90 | 188 ++ props/basc/compf.f90 | 195 +++ props/basc/compm.f90 | 50 + props/basc/compw.f90 | 180 ++ props/basc/cpf.f90 | 176 ++ props/basc/cpw.f90 | 179 ++ props/basc/disp.f90 | 50 + props/basc/kx.f90 | 54 + props/basc/ky.f90 | 54 + props/basc/kz.f90 | 50 + props/basc/lamf.f90 | 123 ++ props/basc/lamm.f90 | 128 ++ props/basc/lamw.f90 | 77 + props/basc/lx.f90 | 98 ++ props/basc/ly.f90 | 98 ++ props/basc/lz.f90 | 98 ++ props/basc/por.f90 | 49 + props/basc/props_check.f90 | 63 + props/basc/props_end.f90 | 37 + props/basc/props_init.f90 | 41 + props/basc/qc.f90 | 55 + props/basc/qf.f90 | 50 + props/basc/qt.f90 | 51 + props/basc/rce.f90 | 84 + props/basc/read_props.f90 | 37 + props/basc/rhocf.f90 | 62 + props/basc/rhocm.f90 | 62 + props/basc/rhof.f90 | 127 ++ props/basc/rhow.f90 | 105 ++ props/basc/visf.f90 | 112 ++ props/basc/visw.f90 | 124 ++ props/const/check_domain.f90 | 188 ++ props/const/compf.f90 | 50 + props/const/compm.f90 | 49 + props/const/cpf.f90 | 50 + props/const/disp.f90 | 50 + props/const/kx.f90 | 54 + props/const/ky.f90 | 54 + props/const/kz.f90 | 50 + props/const/lamf.f90 | 49 + props/const/lx.f90 | 72 + props/const/ly.f90 | 72 + props/const/lz.f90 | 71 + props/const/mod_const.f90 | 64 + props/const/por.f90 | 49 + props/const/props_check.f90 | 63 + props/const/props_end.f90 | 37 + props/const/props_init.f90 | 41 + props/const/qc.f90 | 55 + props/const/qf.f90 | 50 + props/const/qt.f90 | 51 + props/const/rce.f90 | 84 + props/const/read_props.f90 | 116 ++ props/const/rhocf.f90 | 47 + props/const/rhocm.f90 | 50 + props/const/rhof.f90 | 51 + props/const/visf.f90 | 50 + props/ghe/check_domain.f90 | 188 ++ props/ghe/compf.f90 | 192 ++ props/ghe/compm.f90 | 50 + props/ghe/cpf.f90 | 198 +++ props/ghe/disp.f90 | 50 + props/ghe/ghe_array.f90 | 54 + props/ghe/ghe_hpr.f90 | 161 ++ props/ghe/kx.f90 | 72 + props/ghe/ky.f90 | 72 + props/ghe/kz.f90 | 69 + props/ghe/lamf.f90 | 84 + props/ghe/lamm.f90 | 128 ++ props/ghe/lx.f90 | 66 + props/ghe/ly.f90 | 65 + props/ghe/lz.f90 | 64 + props/ghe/por.f90 | 49 + props/ghe/props_check.f90 | 63 + props/ghe/props_end.f90 | 37 + props/ghe/props_init.f90 | 41 + props/ghe/qc.f90 | 55 + props/ghe/qf.f90 | 50 + props/ghe/qt.f90 | 72 + props/ghe/rce.f90 | 84 + props/ghe/read_props.f90 | 37 + props/ghe/rhocf.f90 | 62 + props/ghe/rhocm.f90 | 62 + props/ghe/rhof.f90 | 169 ++ props/ghe/visf.f90 | 167 ++ props/ice/check_domain.f90 | 115 ++ props/ice/compf.f90 | 115 ++ props/ice/compm.f90 | 46 + props/ice/compw.f90 | 69 + props/ice/cpf.f90 | 113 ++ props/ice/cpi.f90 | 66 + props/ice/disp.f90 | 40 + props/ice/ftheta.f90 | 139 ++ props/ice/ice.f90 | 33 + props/ice/ice.inc | 23 + props/ice/ice_allocate.f90 | 57 + props/ice/kx.f90 | 63 + props/ice/ky.f90 | 63 + props/ice/kz.f90 | 63 + props/ice/lamf.f90 | 62 + props/ice/lami.f90 | 61 + props/ice/lamm.f90 | 54 + props/ice/lx.f90 | 76 + props/ice/ly.f90 | 75 + props/ice/lz.f90 | 74 + props/ice/por.f90 | 41 + props/ice/props_check.f90 | 56 + props/ice/props_init.f90 | 81 + props/ice/qc.f90 | 39 + props/ice/qf.f90 | 38 + props/ice/qt.f90 | 43 + props/ice/rce.f90 | 74 + props/ice/read_props.f90 | 86 + props/ice/rhocf.f90 | 53 + props/ice/rhoci.f90 | 50 + props/ice/rhocm.f90 | 49 + props/ice/rhof.f90 | 104 ++ props/ice/rhoi.f90 | 50 + props/ice/rhow.f90 | 134 ++ props/ice/visf.f90 | 102 ++ shem_fw.f90 | 137 ++ solve/CMakeLists.txt | 30 + solve/OMP_TOOLS.f90 | 52 + solve/OMP_TOOLS.inc | 26 + solve/counter.f90 | 54 + solve/ddl_du.f90 | 114 ++ solve/dense_solve.f90 | 106 ++ solve/direct_solve.f90 | 165 ++ solve/get_dnorm.f90 | 57 + solve/get_norm.f90 | 59 + solve/get_norm2.f90 | 60 + solve/mod_OMP_TOOLS.f90 | 27 + solve/mod_blocking_size.f90 | 43 + solve/norm_linsys.f90 | 83 + solve/norm_linsys2.f90 | 84 + solve/norm_resid.f90 | 46 + solve/omp_abbruch.f90 | 277 +++ solve/omp_bayes_solve.f90 | 190 ++ solve/omp_damax.f90 | 83 + solve/omp_ddot.f90 | 259 +++ solve/omp_gen_solve.f90 | 207 +++ solve/omp_gen_solve_diag.f90 | 208 +++ solve/omp_gen_solve_ilu.f90 | 326 ++++ solve/omp_gen_solve_ssor.f90 | 225 +++ solve/omp_mvp.f90 | 345 ++++ solve/omp_mvp2.f90 | 418 +++++ solve/omp_preconditioners.f90 | 1100 ++++++++++++ solve/omp_sym_solve.f90 | 180 ++ solve/omp_sym_solve_diag.f90 | 181 ++ solve/omp_sym_solve_ilu.f90 | 302 ++++ solve/omp_sym_solve_ssor.f90 | 196 +++ solve/p_pos_anz.f90 | 101 ++ solve/par_tools.f90 | 81 + solve/pre_bicgstab.f90 | 580 ++++++ solve/pre_bicgstab.inc | 86 + solve/pre_cg.f90 | 540 ++++++ solve/pre_cg.inc | 66 + solve/preconditioners.f90 | 76 + solve/prepare_solve.f90 | 317 ++++ solve/qddot.f90 | 130 ++ solve/reduction.f90 | 87 + solve/set_dval.f90 | 60 + solve/set_ival.f90 | 60 + solve/set_lval.f90 | 60 + solve/solve.f90 | 181 ++ solve/solve_debug.f90 | 124 ++ solve/solve_type.f90 | 231 +++ solve/ssor_mvp_single.f90 | 154 ++ solve/test_matrix.f90 | 152 ++ solve/test_symmetry.f90 | 72 + solve/test_zero.f90 | 81 + user/none/calc_user.f90 | 57 + user/none/user_check.f90 | 50 + user/none/write_monitor_user.f90 | 81 + user/none/write_user.f90 | 65 + user/wells3d/calc_user.f90 | 187 ++ user/wells3d/mod_wells3d.f90 | 47 + user/wells3d/user_check.f90 | 50 + user/wells3d/write_monitor_user.f90 | 81 + user/wells3d/write_user.f90 | 65 + version.inc.in | 15 + 347 files changed, 45917 insertions(+) create mode 100644 .gitignore create mode 100644 .gitlab/issue_templates/Error.md create mode 100644 CMakeLists.txt create mode 100644 LICENSE.md create mode 100644 cmake/AD.cmake create mode 100644 cmake/Dependencies.cmake create mode 100644 cmake/Flags.cmake create mode 100644 cmake/Options.cmake create mode 100644 cmake/Packages.cmake create mode 100644 cmake/Sources.cmake create mode 100644 doc/Doxyfile create mode 100644 doc/doc_image/cube.png create mode 100644 forward/alloc_arrays.f90 create mode 100644 forward/alloc_data.f90 create mode 100644 forward/arrays.f90 create mode 100644 forward/bhpr.f90 create mode 100644 forward/check_change.f90 create mode 100644 forward/check_props.f90 create mode 100644 forward/check_units.f90 create mode 100644 forward/conc/calc_conc.f90 create mode 100644 forward/conc/cfluxes.f90 create mode 100644 forward/conc/neumann_conc.f90 create mode 100644 forward/conc/peclet_conc.f90 create mode 100644 forward/conc/set_cbc.f90 create mode 100644 forward/conc/set_ccoef.f90 create mode 100644 forward/conc/set_cq.f90 create mode 100644 forward/converged.f90 create mode 100644 forward/courant.f90 create mode 100644 forward/ctrlut/decntrl3.f90 create mode 100644 forward/ctrlut/decntrl4.f90 create mode 100644 forward/ctrlut/encntrl3.f90 create mode 100644 forward/ctrlut/encntrl4.f90 create mode 100644 forward/ctrlut/ijk_m.f90 create mode 100644 forward/ctrlut/m_ijk.f90 create mode 100644 forward/dealloc_arrays.f90 create mode 100644 forward/deltat.f90 create mode 100644 forward/forward_init.f90 create mode 100644 forward/forward_iter.f90 create mode 100644 forward/forward_picard.f90 create mode 100644 forward/forward_preparation.f90 create mode 100644 forward/forward_wrapper.f90 create mode 100644 forward/forward_write.f90 create mode 100644 forward/get_tpbcalbe.f90 create mode 100644 forward/head/calc_head.f90 create mode 100644 forward/head/hbuoy.f90 create mode 100644 forward/head/head2pres.f90 create mode 100644 forward/head/hfluxes.f90 create mode 100644 forward/head/hstor.f90 create mode 100644 forward/head/neumann_head.f90 create mode 100644 forward/head/omp_head2pres.f90 create mode 100644 forward/head/set_hbc.f90 create mode 100644 forward/head/set_hcoef.f90 create mode 100644 forward/head/set_hq.f90 create mode 100644 forward/input/calc_deltatime.f90 create mode 100644 forward/input/read_array.f90 create mode 100644 forward/input/read_bc.f90 create mode 100644 forward/input/read_check.f90 create mode 100644 forward/input/read_control.f90 create mode 100644 forward/input/read_data.f90 create mode 100644 forward/input/read_model.f90 create mode 100644 forward/input/read_property.f90 create mode 100644 forward/input/read_split.f90 create mode 100644 forward/input/read_time.f90 create mode 100644 forward/mathfuncs/alfa.f90 create mode 100644 forward/mathfuncs/amean.f90 create mode 100644 forward/mathfuncs/interpolate_lin.f90 create mode 100644 forward/mathfuncs/interpolate_pol.f90 create mode 100644 forward/mathfuncs/mean3d.f90 create mode 100644 forward/mod_conc.f90 create mode 100644 forward/mod_data.f90 create mode 100644 forward/mod_flow.f90 create mode 100644 forward/mod_genrl.f90 create mode 100644 forward/mod_genrlc.f90 create mode 100644 forward/mod_linfos.f90 create mode 100644 forward/mod_temp.f90 create mode 100644 forward/mod_time.f90 create mode 100644 forward/model_init.f90 create mode 100644 forward/nlrelaxad.f90 create mode 100644 forward/no_ext_link.f90 create mode 100644 forward/old_restore.f90 create mode 100644 forward/old_save.f90 create mode 100644 forward/omp_bindtools.f90 create mode 100644 forward/omp_file_handler.f90 create mode 100644 forward/omp_libnuma.c create mode 100644 forward/omp_summe.f90 create mode 100644 forward/output/write_data.f90 create mode 100644 forward/output/write_dense3d.f90 create mode 100644 forward/output/write_logs.f90 create mode 100644 forward/output/write_monitor.f90 create mode 100644 forward/output/write_outt.f90 create mode 100644 forward/output/write_status_log.f90 create mode 100644 forward/output/write_tecdiff.f90 create mode 100644 forward/output/write_tecplot.f90 create mode 100644 forward/output/write_tecplotc.f90 create mode 100644 forward/output/write_text.f90 create mode 100644 forward/output/write_vtk.f90 create mode 100644 forward/pres/calc_pres.f90 create mode 100644 forward/pres/neumann_pres.f90 create mode 100644 forward/pres/omp_pres2head.f90 create mode 100644 forward/pres/pbuoy.f90 create mode 100644 forward/pres/pfluxes.f90 create mode 100644 forward/pres/pres2head.f90 create mode 100644 forward/pres/pstor.f90 create mode 100644 forward/pres/set_pbc.f90 create mode 100644 forward/pres/set_pcoef.f90 create mode 100644 forward/pres/set_pq.f90 create mode 100644 forward/save_data.f90 create mode 100644 forward/set_tsal.f90 create mode 100644 forward/set_var_deltat.f90 create mode 100644 forward/shemach/compress_file.f90 create mode 100644 forward/shemach/sys_cputime.f90 create mode 100644 forward/shemach/sys_mkdir.f90 create mode 100644 forward/stab_param.f90 create mode 100644 forward/static_relaxation.f90 create mode 100644 forward/strngut/beginlast.f90 create mode 100644 forward/strngut/cfirst.f90 create mode 100644 forward/strngut/chln.f90 create mode 100644 forward/strngut/clast.f90 create mode 100644 forward/strngut/found.f90 create mode 100644 forward/strngut/get_arg.f90 create mode 100644 forward/strngut/lblank.f90 create mode 100644 forward/strngut/locstr.f90 create mode 100644 forward/strngut/sfirst.f90 create mode 100644 forward/temp/calc_temp.f90 create mode 100644 forward/temp/neumann_temp.f90 create mode 100644 forward/temp/peclet_temp.f90 create mode 100644 forward/temp/set_tbc.f90 create mode 100644 forward/temp/set_tcoef.f90 create mode 100644 forward/temp/set_tq.f90 create mode 100644 forward/temp/tfluxes.f90 create mode 100644 forward/test_opt.f90 create mode 100644 hdf5/close_hdf5.f90 create mode 100644 hdf5/closeopen_hdf5.f90 create mode 100644 hdf5/mod_hdf5_vars.f90 create mode 100644 hdf5/mod_input_file_parser_hdf5.f90 create mode 100644 hdf5/open_hdf5.f90 create mode 100644 hdf5/read_hdf5.f90 create mode 100644 hdf5/read_hdf5_int.f90 create mode 100644 hdf5/test_hdf5.f90 create mode 100644 hdf5/write_all_hdf5.f90 create mode 100644 props/bas/check_domain.f90 create mode 100644 props/bas/compf.f90 create mode 100644 props/bas/compm.f90 create mode 100644 props/bas/cpf.f90 create mode 100644 props/bas/disp.f90 create mode 100644 props/bas/kx.f90 create mode 100644 props/bas/ky.f90 create mode 100644 props/bas/kz.f90 create mode 100644 props/bas/lamf.f90 create mode 100644 props/bas/lamm.f90 create mode 100644 props/bas/lx.f90 create mode 100644 props/bas/ly.f90 create mode 100644 props/bas/lz.f90 create mode 100644 props/bas/por.f90 create mode 100644 props/bas/props_check.f90 create mode 100644 props/bas/props_end.f90 create mode 100644 props/bas/props_init.f90 create mode 100644 props/bas/qc.f90 create mode 100644 props/bas/qf.f90 create mode 100644 props/bas/qt.f90 create mode 100644 props/bas/rce.f90 create mode 100644 props/bas/read_props.f90 create mode 100644 props/bas/rhocf.f90 create mode 100644 props/bas/rhocm.f90 create mode 100644 props/bas/rhof.f90 create mode 100644 props/bas/visf.f90 create mode 100644 props/basc/check_domain.f90 create mode 100644 props/basc/compf.f90 create mode 100644 props/basc/compm.f90 create mode 100644 props/basc/compw.f90 create mode 100644 props/basc/cpf.f90 create mode 100644 props/basc/cpw.f90 create mode 100644 props/basc/disp.f90 create mode 100644 props/basc/kx.f90 create mode 100644 props/basc/ky.f90 create mode 100644 props/basc/kz.f90 create mode 100644 props/basc/lamf.f90 create mode 100644 props/basc/lamm.f90 create mode 100644 props/basc/lamw.f90 create mode 100644 props/basc/lx.f90 create mode 100644 props/basc/ly.f90 create mode 100644 props/basc/lz.f90 create mode 100644 props/basc/por.f90 create mode 100644 props/basc/props_check.f90 create mode 100644 props/basc/props_end.f90 create mode 100644 props/basc/props_init.f90 create mode 100644 props/basc/qc.f90 create mode 100644 props/basc/qf.f90 create mode 100644 props/basc/qt.f90 create mode 100644 props/basc/rce.f90 create mode 100644 props/basc/read_props.f90 create mode 100644 props/basc/rhocf.f90 create mode 100644 props/basc/rhocm.f90 create mode 100644 props/basc/rhof.f90 create mode 100644 props/basc/rhow.f90 create mode 100644 props/basc/visf.f90 create mode 100644 props/basc/visw.f90 create mode 100644 props/const/check_domain.f90 create mode 100644 props/const/compf.f90 create mode 100644 props/const/compm.f90 create mode 100644 props/const/cpf.f90 create mode 100644 props/const/disp.f90 create mode 100644 props/const/kx.f90 create mode 100644 props/const/ky.f90 create mode 100644 props/const/kz.f90 create mode 100644 props/const/lamf.f90 create mode 100644 props/const/lx.f90 create mode 100644 props/const/ly.f90 create mode 100644 props/const/lz.f90 create mode 100644 props/const/mod_const.f90 create mode 100644 props/const/por.f90 create mode 100644 props/const/props_check.f90 create mode 100644 props/const/props_end.f90 create mode 100644 props/const/props_init.f90 create mode 100644 props/const/qc.f90 create mode 100644 props/const/qf.f90 create mode 100644 props/const/qt.f90 create mode 100644 props/const/rce.f90 create mode 100644 props/const/read_props.f90 create mode 100644 props/const/rhocf.f90 create mode 100644 props/const/rhocm.f90 create mode 100644 props/const/rhof.f90 create mode 100644 props/const/visf.f90 create mode 100644 props/ghe/check_domain.f90 create mode 100644 props/ghe/compf.f90 create mode 100644 props/ghe/compm.f90 create mode 100644 props/ghe/cpf.f90 create mode 100644 props/ghe/disp.f90 create mode 100644 props/ghe/ghe_array.f90 create mode 100644 props/ghe/ghe_hpr.f90 create mode 100644 props/ghe/kx.f90 create mode 100644 props/ghe/ky.f90 create mode 100644 props/ghe/kz.f90 create mode 100644 props/ghe/lamf.f90 create mode 100644 props/ghe/lamm.f90 create mode 100644 props/ghe/lx.f90 create mode 100644 props/ghe/ly.f90 create mode 100644 props/ghe/lz.f90 create mode 100644 props/ghe/por.f90 create mode 100644 props/ghe/props_check.f90 create mode 100644 props/ghe/props_end.f90 create mode 100644 props/ghe/props_init.f90 create mode 100644 props/ghe/qc.f90 create mode 100644 props/ghe/qf.f90 create mode 100644 props/ghe/qt.f90 create mode 100644 props/ghe/rce.f90 create mode 100644 props/ghe/read_props.f90 create mode 100644 props/ghe/rhocf.f90 create mode 100644 props/ghe/rhocm.f90 create mode 100644 props/ghe/rhof.f90 create mode 100644 props/ghe/visf.f90 create mode 100644 props/ice/check_domain.f90 create mode 100644 props/ice/compf.f90 create mode 100644 props/ice/compm.f90 create mode 100644 props/ice/compw.f90 create mode 100644 props/ice/cpf.f90 create mode 100644 props/ice/cpi.f90 create mode 100644 props/ice/disp.f90 create mode 100644 props/ice/ftheta.f90 create mode 100644 props/ice/ice.f90 create mode 100644 props/ice/ice.inc create mode 100644 props/ice/ice_allocate.f90 create mode 100644 props/ice/kx.f90 create mode 100644 props/ice/ky.f90 create mode 100644 props/ice/kz.f90 create mode 100644 props/ice/lamf.f90 create mode 100644 props/ice/lami.f90 create mode 100644 props/ice/lamm.f90 create mode 100644 props/ice/lx.f90 create mode 100644 props/ice/ly.f90 create mode 100644 props/ice/lz.f90 create mode 100644 props/ice/por.f90 create mode 100644 props/ice/props_check.f90 create mode 100644 props/ice/props_init.f90 create mode 100644 props/ice/qc.f90 create mode 100644 props/ice/qf.f90 create mode 100644 props/ice/qt.f90 create mode 100644 props/ice/rce.f90 create mode 100644 props/ice/read_props.f90 create mode 100644 props/ice/rhocf.f90 create mode 100644 props/ice/rhoci.f90 create mode 100644 props/ice/rhocm.f90 create mode 100644 props/ice/rhof.f90 create mode 100644 props/ice/rhoi.f90 create mode 100644 props/ice/rhow.f90 create mode 100644 props/ice/visf.f90 create mode 100644 shem_fw.f90 create mode 100644 solve/CMakeLists.txt create mode 100644 solve/OMP_TOOLS.f90 create mode 100644 solve/OMP_TOOLS.inc create mode 100644 solve/counter.f90 create mode 100644 solve/ddl_du.f90 create mode 100644 solve/dense_solve.f90 create mode 100644 solve/direct_solve.f90 create mode 100644 solve/get_dnorm.f90 create mode 100644 solve/get_norm.f90 create mode 100644 solve/get_norm2.f90 create mode 100644 solve/mod_OMP_TOOLS.f90 create mode 100644 solve/mod_blocking_size.f90 create mode 100644 solve/norm_linsys.f90 create mode 100644 solve/norm_linsys2.f90 create mode 100644 solve/norm_resid.f90 create mode 100644 solve/omp_abbruch.f90 create mode 100644 solve/omp_bayes_solve.f90 create mode 100644 solve/omp_damax.f90 create mode 100644 solve/omp_ddot.f90 create mode 100644 solve/omp_gen_solve.f90 create mode 100644 solve/omp_gen_solve_diag.f90 create mode 100644 solve/omp_gen_solve_ilu.f90 create mode 100644 solve/omp_gen_solve_ssor.f90 create mode 100644 solve/omp_mvp.f90 create mode 100644 solve/omp_mvp2.f90 create mode 100644 solve/omp_preconditioners.f90 create mode 100644 solve/omp_sym_solve.f90 create mode 100644 solve/omp_sym_solve_diag.f90 create mode 100644 solve/omp_sym_solve_ilu.f90 create mode 100644 solve/omp_sym_solve_ssor.f90 create mode 100644 solve/p_pos_anz.f90 create mode 100644 solve/par_tools.f90 create mode 100644 solve/pre_bicgstab.f90 create mode 100644 solve/pre_bicgstab.inc create mode 100644 solve/pre_cg.f90 create mode 100644 solve/pre_cg.inc create mode 100644 solve/preconditioners.f90 create mode 100644 solve/prepare_solve.f90 create mode 100644 solve/qddot.f90 create mode 100644 solve/reduction.f90 create mode 100644 solve/set_dval.f90 create mode 100644 solve/set_ival.f90 create mode 100644 solve/set_lval.f90 create mode 100644 solve/solve.f90 create mode 100644 solve/solve_debug.f90 create mode 100644 solve/solve_type.f90 create mode 100644 solve/ssor_mvp_single.f90 create mode 100644 solve/test_matrix.f90 create mode 100644 solve/test_symmetry.f90 create mode 100644 solve/test_zero.f90 create mode 100644 user/none/calc_user.f90 create mode 100644 user/none/user_check.f90 create mode 100644 user/none/write_monitor_user.f90 create mode 100644 user/none/write_user.f90 create mode 100644 user/wells3d/calc_user.f90 create mode 100644 user/wells3d/mod_wells3d.f90 create mode 100644 user/wells3d/user_check.f90 create mode 100644 user/wells3d/write_monitor_user.f90 create mode 100644 user/wells3d/write_user.f90 create mode 100644 version.inc.in diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..21a29a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +Makefile.dep +Makefile.flags +version.inc +test_integer.exe +*.mod +*.o \ No newline at end of file diff --git a/.gitlab/issue_templates/Error.md b/.gitlab/issue_templates/Error.md new file mode 100644 index 0000000..cadfb28 --- /dev/null +++ b/.gitlab/issue_templates/Error.md @@ -0,0 +1,23 @@ +Error message +------------- +``` +(Insert Error message here) +``` + +Error Description +----------------- +(Concisely describe the error here.) + +Gitlab Branch +------------- +`(Insert Gitlab branch)` + +Status Log +---------- +``` +(Insert MODELNAME_status.log) +``` +or (even better) +``` +(Insert Makefile.flags - generated during compilation) +``` diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c79e718 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,93 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +cmake_minimum_required(VERSION 3.12 FATAL_ERROR) +project(SHEMAT-Suite VERSION 9.00 DESCRIPTION "Freely" LANGUAGES Fortran) + +enable_language(Fortran C CXX) +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CMAKE_CURRENT_LIST_DIR}/cmake/) + +# Executable sources +file(GLOB SRC_MAIN_FW shem_fw.f90) +file(GLOB SRC_MAIN_AD shem_ad.f90) +file(GLOB SRC_MAIN_DD shem_dd.f90) +file(GLOB SRC_MAIN_SM shem_sm.f90) + + +include(cmake/Options.cmake) +include(cmake/Sources.cmake) +include(cmake/Flags.cmake) +include(cmake/Packages.cmake) +include(cmake/Dependencies.cmake) +include(cmake/AD.cmake) + + + +set(FW_NAME "shem_fw_${PROPS}.x") +add_executable(${FW_NAME} ${SRC_MAIN_FW} ${SRC_FORWARD}) + +set(AD_NAME "shem_ad_${PROPS}.x") +add_executable(${AD_NAME} EXCLUDE_FROM_ALL ${SRC_MAIN_AD} ${SRC_INVERSE}) + +set(DD_NAME "shem_dd_${PROPS}.x") +add_executable(${DD_NAME} EXCLUDE_FROM_ALL ${SRC_MAIN_DD} ${SRC_INVERSE}) + +set(SM_NAME "shem_sm_${PROPS}.x") +add_executable(${SM_NAME} EXCLUDE_FROM_ALL ${SRC_MAIN_SM} ${SRC_SIMUL}) + +# Library Sources +file(GLOB SRC_LIB_SHEMAT shem_fl.f90) +file(GLOB SRC_LIB_SHEMAT_PARAMETER shem_parameter.f90) + +#Shortcut Make Targets +add_custom_target(fw DEPENDS ${FW_NAME}) +add_custom_target(ad DEPENDS ${AD_NAME}) +add_custom_target(dd DEPENDS ${DD_NAME}) +add_custom_target(sm DEPENDS ${SM_NAME}) + +target_compile_definitions(${AD_NAME} PUBLIC -DAD -Dset${ADTYPE}) +if (NOT ${NLSOLVETYPE} MATCHES "stdFW") + target_compile_definitions(${FW_NAME} PUBLIC -D${NLSOLVETYPE} -DAD -Dset${ADTYPE}) + target_include_directories(${FW_NAME} PUBLIC nonlinear/nitsol/Nitsol) +else() + add_definitions(-DstdFW) +endif() + + +if(use_rm) + target_compile_definitions(${AD_NAME} PUBLIC -DJACOBI_FREE -DAD_RM -Dset${AD_RMTYPE}) +endif() +target_compile_definitions(${DD_NAME} PUBLIC -DAD -Dset${ADTYPE}) + + +add_library("shemat_oed" EXCLUDE_FROM_ALL ${SRC_LIB_SHEMAT} ${SRC_INVERSE} ${SRC_BLAS} ${SRC_LAPACK}) +target_compile_definitions("shemat_oed" PUBLIC -DAD -Dset${ADTYPE}) +target_compile_options("shemat_oed" PUBLIC -fPIC) + + +add_library("shemat_parameter" EXCLUDE_FROM_ALL ${SRC_LIB_SHEMAT_PARAMETER} ${SRC_INVERSE} ${SRC_BLAS} ${SRC_LAPACK}) +target_compile_definitions("shemat_parameter" PUBLIC -DMF_STBAY -DAD -Dset${ADTYPE} -Dmatvec -DAD_RM -DJACOBI_FREE) +target_compile_options("shemat_parameter" PUBLIC -fPIC) + + +add_custom_target(lib_oed DEPENDS "shemat_oed") +add_custom_target(lib_parameter DEPENDS "shemat_parameter") diff --git a/LICENSE.md b/LICENSE.md new file mode 100644 index 0000000..a5a7f74 --- /dev/null +++ b/LICENSE.md @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 SHEMAT-Suite + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/cmake/AD.cmake b/cmake/AD.cmake new file mode 100644 index 0000000..355a1d4 --- /dev/null +++ b/cmake/AD.cmake @@ -0,0 +1,148 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +# Standard AD USER and PROPS +set(USERS_PROP "basc") +set(PROPS_USER "wells3d") + +# AD Forward targets +#=================== +add_custom_target(ad_exports + COMMAND + export forward_lst="${AD_DIRECTORIES}"; export users_lst="${USER_DIRECTORIES}"; export props_lst="${PROPS_DIRECTORIES}"; export props_user="${USERS_PROP}";export users_prop="${PROPS_USER}" + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "export the propper ad bash variables" +) + +add_custom_target(tap_tlm_users_prepare + DEPENDS ad_exports + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER_DIRECTORIES}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' prepare +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "prepare user functions for automatic differentiation with tapenade" +) + + +add_custom_target(tap_tlm_users_tlm + DEPENDS tap_tlm_users_prepare + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER_DIRECTORIES}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' tlm + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "execute user automatic differentiation with tapenade and copy the results" +) + +add_custom_target(tap_tlm_props_prepare + DEPENDS tap_tlm_users_tlm + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${PROPS_USER}' props_lst='${PROPS_DIRECTORIES}' forward_lst='${AD_DIRECTORIES}' prepare + #echo "TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' prepare" +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "prepare props functions for automatic differentiation with tapenade" +) + + +add_custom_target(tap_tlm_props_tlm + DEPENDS tap_tlm_props_prepare + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${PROPS_USER}' props_lst='${PROPS_DIRECTORIES}' forward_lst='${AD_DIRECTORIES}' tlm + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "execute props automatic differentiation with tapenade and copy results" +) +add_custom_target(tap_tlm + DEPENDS tap_tlm_props_tlm + COMMAND + export forward_lst="${AD_DIRECTORIES}" users_lst="${USER_DIRECTORIES}" props_lst="${PROPS_DIRECTORIES}" props_user="${PROPS_USER}" users_prop=${USERS_PROP} phys_base="${phys_base}" && + ./mkAD/mv_tap_tlm && + rm user/none/g_tap/${phys_base}/calc_user_ftl.f90 && + rm -fr g_tap/${phys_base}/*_nodiff.f* g_tap/${phys_base}/daxpy_ftl.f* g_tap/${phys_base}/dcopy_ftl.f* g_tap/${phys_base}/dscal_ftl.f* props/*/g_tap/${phys_base}/*_nodiff*.* user/*/g_tap/${phys_base}/*_nodiff*.f90 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "AD Differentiation with Tapenade" + ) + +add_custom_target(tap_tlm_clean + COMMAND + rm -fr ${CMAKE_CURRENT_SOURCE_DIR}/props/*/g_tap/${phys_base} ${CMAKE_CURRENT_SOURCE_DIR}/user/*/g_tap/${phys_base} ${CMAKE_CURRENT_SOURCE_DIR}/g_tap/${phys_base} + COMMENT "Cleaning Tapenade TLM directories" + ) + + +# AD Reverse targets +#=================== +add_custom_target(tap_adm_users_prepare + DEPENDS ad_exports + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER_DIRECTORIES}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' prepare_reverse +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "prepare user functions for automatic differentiation with tapenade" +) + + +add_custom_target(tap_adm_users_adm + DEPENDS tap_adm_users_prepare + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER_DIRECTORIES}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' adm + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "execute user automatic differentiation with tapenade and copy the results" +) + +add_custom_target(tap_adm_props_prepare + DEPENDS tap_adm_users_adm + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${PROPS_USER}' props_lst='${PROPS_DIRECTORIES}' forward_lst='${AD_DIRECTORIES}' prepare_reverse + #echo "TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${USER}' props_lst='${USERS_PROP}' forward_lst='${AD_DIRECTORIES}' prepare" +WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "prepare props functions for automatic differentiation with tapenade" +) + + +add_custom_target(tap_adm_props_adm + DEPENDS tap_adm_props_prepare + COMMAND + make TOOL=tap phys_base='${phys_base}' ad_mode='full' users_lst='${PROPS_USER}' props_lst='${PROPS_DIRECTORIES}' forward_lst='${AD_DIRECTORIES}' adm + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/mkAD + COMMENT + "execute props automatic differentiation with tapenade and copy results" +) +add_custom_target(tap_adm + DEPENDS tap_adm_props_adm + COMMAND + export forward_lst="${AD_DIRECTORIES}" users_lst="${USER_DIRECTORIES}" props_lst="${PROPS_DIRECTORIES}" props_user="${PROPS_USER}" users_prop=${USERS_PROP} phys_base="${phys_base}" && + ./mkAD/mv_tap_adm #&& + #rm user/none/ad_tap/ad_calc_user.f90 && + #rm -fr ad_tap/*_nodiff.f* ad_tap/daxpy_ftl.f* ad_tap/dcopy_ftl.f* ad_tap/dscal_ftl.f* props/*/ad_tap/*_nodiff.* user/*/ad_tap/*_nodiff.f90 + WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} + COMMENT "AD Differentiation with Tapenade" + ) + +add_custom_target(tap_adm_clean + COMMAND + rm -fr ${CMAKE_CURRENT_SOURCE_DIR}/props/*/ad_tap/${phys_base}\${CMAKE_CURRENT_SOURCE_DIR}/user/*/ad_tap/${phys_base} ${CMAKE_CURRENT_SOURCE_DIR}/ad_tap/${phys_base} + COMMENT "Cleaning Tapenade TLM directories" + ) diff --git a/cmake/Dependencies.cmake b/cmake/Dependencies.cmake new file mode 100644 index 0000000..e8bca26 --- /dev/null +++ b/cmake/Dependencies.cmake @@ -0,0 +1,76 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#==================================================== +#Generate version.inc +#==================================================== +string(TIMESTAMP _configuration_time "%Y-%m-%d %H:%M:%S [UTC]" UTC) +configure_file(version.inc.in generated/version.inc @ONLY) +#==================================================== + + +#==================================================== +#This section is for updating forward/input/read_check.f90 with newly implemented reading paramters +#==================================================== +#Read all read_*.f90 files and put the parameter names in @read_cur_use +FOREACH(fname ${read_files}) + file(STRINGS ${fname} cur_file REGEX "^[^c^C^!].*found.*(\#|key_char//') [a-zA-Z0-9 _]+.*") + #message("${cur_file}") + foreach(str ${cur_file}) + # message("str=${str}") + string(REGEX REPLACE ".*'(\#| )([a-zA-Z0-9_]*)(:|'| ).*" "\\2" cur ${str}) + list(APPEND read_cur_use ${cur}) + endforeach() +ENDFOREACH() +list(REMOVE_DUPLICATES read_cur_use) +list(SORT read_cur_use) + +#Read all parameters we are currently checking in read_check.f90, store them in @read_check_use +file(STRINGS forward/input/read_check.f90 check_file_content REGEX "key_char//") +foreach(str ${check_file_content}) + string(REGEX REPLACE ".*'(\#| )([a-zA-Z0-9_]*)(:|'| ).*" "\\2" cur ${str}) + list(APPEND read_check_use ${cur}) +endforeach() +list(REMOVE_DUPLICATES read_check_use) +list(SORT read_check_use) + +#Now remove all the parameters we are currently checking from the @read_cur_use list +list(REMOVE_ITEM read_cur_use ${read_check_use}) + +# Do we need to update read_check.f90 with missing parameters in read_cur_use? +if (read_cur_use) + message("We have to update read_check.f90 with ${read_cur_use}") + file(STRINGS forward/input/read_check.f90 check_file_content) + set(automatic_section ${check_file_content}) + list(FILTER automatic_section INCLUDE REGEX ".*automatic generated.*") + list(FIND check_file_content "${automatic_section}" automatic_element) + MATH(EXPR automatic_element "${automatic_element}+1") + foreach(item ${read_cur_use}) + list(INSERT check_file_content ${automatic_element} " f_entry = f_entry + locstr(line,key_char\/\/' ${item}')") + MATH(EXPR automatic_element "${automatic_element}+1") + endforeach() + file(WRITE forward/input/read_check.f90 "") + foreach(str ${check_file_content}) + file(APPEND forward/input/read_check.f90 "${str}\n") + endforeach() +endif() +#==================================================== diff --git a/cmake/Flags.cmake b/cmake/Flags.cmake new file mode 100644 index 0000000..4736419 --- /dev/null +++ b/cmake/Flags.cmake @@ -0,0 +1,60 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +if("${CMAKE_Fortran_COMPILER_ID}" MATCHES "Intel") + if (NOT debug) + add_compile_options(-w -O3 -vec_report0 -fpp -axSTPW -fp-model fast=2) + else() + add_compile_options(-g -O0 -fpp) + endif() +elseif("${CMAKE_Fortran_COMPILER_ID}" MATCHES "GNU") + if (NOT debug) + add_compile_options(-fno-second-underscore -march=k8 -O3 -funroll-all-loops -fprefetch-loop-arrays -ffast-math -mno-ieee-fp -DG95 -DCLopt -frepack-arrays -ftree-vectorize -funit-at-a-time -cpp) + else() + add_compile_options(-g -O0 -DG95 -cpp) + endif() +endif() +add_definitions(-DUSE_QDDOT) + + +if(NOT use_rm) + add_definitions(-DSTBAY) +endif() + +if (head_base) + add_definitions(-Dhead_base) +elseif(pres_base) + add_definitions(-Dpres_base) +else() + message(FATAL_ERROR "head_base OR pres_base need to be set") +endif() + +add_definitions(-DUSER_${USER} -DPROPS_${PROPS} -DSIMUL_${SIMUL} ) + +if(NOT plt) + add_definitions(-DNOPLT) +endif() + +if(NOT vtk) + add_definitions(-DNOVTK) +endif() + diff --git a/cmake/Options.cmake b/cmake/Options.cmake new file mode 100644 index 0000000..6c836b6 --- /dev/null +++ b/cmake/Options.cmake @@ -0,0 +1,73 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +option(omp "OpenMP switch" ON) +option(hdf "HDF5 switch" ON) +option(mpi "MPI switch" OFF) +option(plt "PLT switch" ON) +option(vtk "VTK switch" ON) +#option(head "Use head based computation" ON) +#option(pres "Use pressure based computation" OFF) +option(details "Show compilation details" OFF) +option(debug "Compile with debug informations" OFF) +option(use_rm "Use Reverse-Mode in Inversion" OFF) + +set(phys_base "head" CACHE INTERNAL "The used physical pressure representation, could be head or pres") +set_property(CACHE phys_base PROPERTY STRINGS "head" "pres") +message(STATUS "phys_base='${phys_base}'") + +set(USER "none" CACHE STRING "The Userfunction to be used (standard is none)") +set(PROPS "const" CACHE STRING "The Properties to be used (standard is const)") + + +# Solvertype for Nonlinear Coupling +set(NLSOLVETYPE "stdFW" CACHE STRING "Nonlinear Solver") +set_property(CACHE NLSOLVETYPE PROPERTY STRINGS "stdFW" "nwtFW" "nitFW") + + +set(ADTYPE "g_tap" CACHE STRING "Used AD forward mode directories") +set(AD_RMTYPE "ad_tap" CACHE STRING "Used AD reverse mode directories") + +set(SIMUL "sgsim" CACHE STRING "Used Simulation (sgsim)") +if (${phys_base} MATCHES "pres") + set(pres_base ON) + set(head_base OFF) +elseif(${phys_base} MATCHES "head") + set(head_base ON) + set(pres_base OFF) +else() + message(FATAL_ERROR "phys_base needs to be set to head OR pres. Add -Dphys_base=head OR -Dphys_base=pres to cmake command [Standard is head]") +endif() + +if(use_rm) + set(matfree ON) +else() + set(matfree OFF) +endif() + +if(details) + set(CMAKE_VERBOSE_MAKEFILE ON) +endif() + +if(debug) + set(CMAKE_BUILD_TYPE Debug) +endif() diff --git a/cmake/Packages.cmake b/cmake/Packages.cmake new file mode 100644 index 0000000..33a3003 --- /dev/null +++ b/cmake/Packages.cmake @@ -0,0 +1,41 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#packages +if(omp) + find_package(OpenMP REQUIRED) + add_compile_options(${OpenMP_Fortran_FLAGS}) + set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${OpenMP_Fortran_FLAGS}") + add_definitions(-DfOMP) +endif() +find_package(BLAS REQUIRED) +link_libraries(${BLAS_LIBRARIES}) +find_package(LAPACK REQUIRED) +link_libraries(${LAPACK_LIBRARIES}) +if(hdf) + find_package(HDF5 REQUIRED COMPONENTS Fortran Fortran_HL) + link_libraries(${HDF5_Fortran_LIBRARIES} ${HDF5_Fortran_HL_LIBRARIES}) + include_directories(${HDF5_INCLUDE_DIRS}) + add_definitions(-DHDF) +else() + add_definitions(-DnoHDF) +endif() diff --git a/cmake/Sources.cmake b/cmake/Sources.cmake new file mode 100644 index 0000000..24cf15b --- /dev/null +++ b/cmake/Sources.cmake @@ -0,0 +1,137 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +#Module Files - need to be build prior to all other files +file (GLOB SRC_MODULES forward/arrays.f90 forward/mod_*.f90 solve/mod_*.f90 hdf5/mod_*.f90) +file (GLOB SRC_MODULES_AD inverse/mod_*.f90 inverse/${ADTYPE}/g_arrays.f90 ${ADTYPE}/g_mod*.f* props/${PROPS}/${ADTYPE}/g_mod*.f*) +file (GLOB SRC_MODULES_SM simul/mod_*.f90 simul/enkf/m_*.f*) + +#Forward Files +file (GLOB SRC_FORWARD forward/*.f* forward/input/*.f* forward/output/*.f* forward/shemach/*.f* forward/strngut/*.f* forward/ctrlut/*.f* + forward/temp/*.f* forward/conc/*.f* forward/mathfuncs/*.f*) +file (GLOB SRC_FORWARD_HEAD forward/head/*.f*) +file (GLOB SRC_FORWARD_PRES forward/pres/*.f*) +if (pres_base) + list(APPEND SRC_FORWARD ${SRC_FORWARD_PRES}) +elseif(head_base) + list(APPEND SRC_FORWARD ${SRC_FORWARD_HEAD}) +endif() + + +#Inverse Files +file(GLOB SRC_INVERSE inverse/*.f* inverse/${ADTYPE}/*.f* ${ADTYPE}/${phys_base}/*.f* blas/${ADTYPE}/*.f*) +if (use_rm) + file(GLOB SRC_ADHELPER mkAD/ADFirstAidKit/adBuffer.f mkAD/ADFirstAidKit/adStack.c) + file(GLOB SRC_MODULES_AD_RM inverse/mod_*.f90 inverse/${AD_RMTYPE}/arrays_ad.f90 inverse/${AD_RMTYPE}/mod_*_ad.f* props/${PROPS}/${AD_RMTYPE}/${phys_base}/mod_*_ad.f*) + list(APPEND SRC_MODULES_AD ${SRC_MODULES_AD_RM}) + file(GLOB SRC_INVERSE_RM inverse/${AD_RMTYPE}/* ${AD_RMTYPE}/${phys_base}/*.f* blas/${AD_RMTYPE}/*.f* props/${PROPS}/${AD_RMTYPE}/${phys_base}/*.f* user/${USER}/${AD_RMTYPE}/${phys_base}/*.f*) + list(APPEND SRC_INVERSE ${SRC_INVERSE_RM} ${SRC_ADHELPER}) +endif() + +#HDF FILES +file(GLOB SRC_HDF hdf5/add_cube.f90 hdf5/open_hdf5.f90 hdf5/close_hdf5.f90 hdf5/closeopen_hdf5.f90 hdf5/test_hdf5.f90 hdf5/read_hdf5.f90 hdf5/read_hdf5_int.f90 hdf5/write_all_hdf5.f90 hdf5/add_line.f90 hdf5/write_parameter2_hdf5.f90 hdf5/add_plane.f90 hdf5/write_parameter_hdf5.f90 hdf5/read_outt_hdf5.f90 ) +#HDF FILES FOR INVERSE +file(GLOB SRC_HDF_AD inverse/mod_inverse.f90 hdf5/write_joutt_hdf5.f90 hdf5/read_joutt_hdf5.f90 hdf5/write_inv_hdf5.f90 ) + + +#Solve Files +file(GLOB SRC_SOLVE solve/counter.f90 solve/mod_blocking_size.f90 solve/omp_mvp2.f90 solve/omp_sym_solve_ilu.f90 solve/preconditioners.f90 solve/solve_debug.f90 +solve/ddl_du.f90 solve/mod_OMP_TOOLS.f90 solve/omp_damax.f90 solve/omp_mvp.f90 solve/omp_sym_solve_ssor.f90 solve/prepare_solve.f90 solve/solve.f90 +solve/dense_solve.f90 solve/nag_gen_solve.f90 solve/omp_ddot.f90 solve/OMP_TOOLS.f90 solve/qddot.f90 solve/solve_type.f90 +solve/direct_solve.f90 solve/norm_linsys2.f90 solve/omp_gen_solve_diag.f90 solve/par_tools.f90 solve/reduction.f90 solve/ssor_mvp_single.f90 +solve/get_dnorm.f90 solve/norm_linsys.f90 solve/omp_gen_solve.f90 solve/omp_preconditioners.f90 solve/p_pos_anz.f90 solve/set_dval.f90 solve/test_matrix.f90 +solve/get_norm2.f90 solve/norm_resid.f90 solve/omp_gen_solve_ilu.f90 solve/omp_sym_solve_diag.f90 solve/pre_bicgstab.f90 solve/set_ival.f90 solve/test_symmetry.f90 +solve/get_norm.f90 solve/omp_abbruch.f90 solve/omp_gen_solve_ssor.f90 solve/omp_sym_solve.f90 solve/pre_cg.f90 solve/set_lval.f90 solve/test_zero.f90 ) + +file(GLOB SRC_SOLVE_AD solve/omp_bayes_solve.f90) + +#Simul Files +file(GLOB SRC_SIMUL simul/*.f* simul/enkf/*.f* simul/gs/*.f* simul/${SIMUL}/*.f*) + +#User Files +file(GLOB SRC_USER user/${USER}/*.f*) +file(GLOB SRC_USER_AD user/${USER}/${ADTYPE}/${phys_base}/*.f*) + +#Props Files +file(GLOB SRC_PROPS props/${PROPS}/*.f*) +list(FILTER SRC_PROPS EXCLUDE REGEX ".*gps\_.*\.f*$") +file(GLOB SRC_PROPS_AD props/${PROPS}/${ADTYPE}/${phys_base}/*.f*) + + +# Include Directories +include_directories("." "forward" "solve" "${PROJECT_BINARY_DIR}/generated/") + + +#Sources for Forward Build +list(APPEND SRC_FORWARD ${SRC_SOLVE} ${SRC_HDF} ${SRC_PROPS} ${SRC_USER} ${SRC_MODULES}) + +#Sources for Inverse Build +list(APPEND SRC_INVERSE ${SRC_FORWARD} ${SRC_HDF_AD} ${SRC_MODULES_AD} ${SRC_USER_AD} ${SRC_PROPS_AD} ${SRC_SOLVE_AD}) +if(pres_base) + list(FILTER SRC_INVERSE EXCLUDE REGEX ".*\_unconf.*\.f*$") +endif() +if(NOT ${NLSOLVETYPE} MATCHES "stdFW") + list(APPEND SRC_FORWARD ${SRC_NONLINEAR} ${SRC_INVERSE}) +endif() + + + +list(APPEND SRC_SIMUL ${SRC_FORWARD} ${SRC_MODULES_SM}) + +file(GLOB read_files */read_*.f* */input/read_*.f* props/*/read_user.f*) +list(FILTER read_files EXCLUDE REGEX ".*forward/input/read_check.f90|.*/input/read_restartFW.f90|.*inverse/read_restartINV.f90") + + +# External library definitions to be used with e.g. EFCOSS +#BLAS Files +file(GLOB SRC_BLAS blas/*.f*) + +#LAPACK Files +file(GLOB SRC_LAPACK lapack/*.f*) + + +#Directories needed for AD generation +list(APPEND AD_DIRECTORIES forward forward/input forward/output forward/shemach forward/strngut forward/ctrlut + forward/temp forward/conc forward/mathfuncs hdf5 solve blas) +if(pres) + list(APPEND AD_DIRECTORIES forward/pres) +else() + list(APPEND AD_DIRECTORIES forward/head) +endif() + +# Define user and property directories for AD generation process (wells3d and basc are required, c.f AD.cmake) +list(APPEND USER_DIRECTORIES wells3d none)# gheexpl)# wells wells6 wells3d_s3w wells3dN_CK wells3dN_CK3B wells3d_fine wells3d_stoch wells3d_stoch_3B wells3d_stoch_s3w gheloop gheexpl) +list(APPEND PROPS_DIRECTORIES basc const bas)# ice kola)# conv basd frac ice kola) + +list(APPEND USER_DIRECTORIES_FULL USER_DIRECTORIES) +list(APPEND PROPS_DIRECTORIES_FULL PROPS_DIRECTORIES) +list(TRANSFORM USER_DIRECTORIES_FULL PREPEND "user/") +list(TRANSFORM PROPS_DIRECTORIES_FULL PREPEND "props/") + + +# All the directories for USER and PROPS variables +file(GLOB ALL_USER_DIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/user user/*) +message(STATUS "Available USER='${ALL_USER_DIRECTORIES}'") +file(GLOB ALL_PROPS_DIRECTORIES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/props props/*) +message(STATUS "Available PROPS='${ALL_PROPS_DIRECTORIES}'") +set_property(CACHE USER PROPERTY STRINGS ${ALL_USER_DIRECTORIES}) +set_property(CACHE PROPS PROPERTY STRINGS ${ALL_PROPS_DIRECTORIES}) diff --git a/doc/Doxyfile b/doc/Doxyfile new file mode 100644 index 0000000..a74ddb7 --- /dev/null +++ b/doc/Doxyfile @@ -0,0 +1,2327 @@ +# Doxyfile 1.8.5 + +# This file describes the settings to be used by the documentation system +# doxygen (www.doxygen.org) for a project. +# +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. +# The format is: +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). + +#--------------------------------------------------------------------------- +# Project related configuration options +#--------------------------------------------------------------------------- + +# This tag specifies the encoding used for all characters in the config file +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. + +DOXYFILE_ENCODING = UTF-8 + +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. + +PROJECT_NAME = Shemat-Suite + +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. + +PROJECT_NUMBER = + +# Using the PROJECT_BRIEF tag one can provide an optional one line description +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. + +PROJECT_BRIEF = + +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. + +PROJECT_LOGO = + +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. + +OUTPUT_DIRECTORY = sources/ + +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. + +CREATE_SUBDIRS = YES + +# The OUTPUT_LANGUAGE tag is used to specify the language in which all +# documentation generated by doxygen is written. Doxygen will use this +# information to generate all constant output in the proper language. +# Possible values are: Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese- +# Traditional, Croatian, Czech, Danish, Dutch, English, Esperanto, Farsi, +# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en, +# Korean, Korean-en, Latvian, Norwegian, Macedonian, Persian, Polish, +# Portuguese, Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, +# Turkish, Ukrainian and Vietnamese. +# The default value is: English. + +OUTPUT_LANGUAGE = English + +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. + +BRIEF_MEMBER_DESC = YES + +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# brief descriptions will be completely suppressed. +# The default value is: YES. + +REPEAT_BRIEF = NO + +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. + +ABBREVIATE_BRIEF = "The $name class" \ + "The $name widget" \ + "The $name file" \ + is \ + provides \ + specifies \ + contains \ + represents \ + a \ + an \ + the + +# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then +# doxygen will generate a detailed section even if there is only a brief +# description. +# The default value is: NO. + +ALWAYS_DETAILED_SEC = NO + +# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all +# inherited members of a class in the documentation of that class as if those +# members were ordinary class members. Constructors, destructors and assignment +# operators of the base classes will not be shown. +# The default value is: NO. + +INLINE_INHERITED_MEMB = NO + +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. + +FULL_PATH_NAMES = YES + +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. + +STRIP_FROM_PATH = ../ + +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. + +STRIP_FROM_INC_PATH = + +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. + +SHORT_NAMES = NO + +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. + +JAVADOC_AUTOBRIEF = NO + +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. + +QT_AUTOBRIEF = NO + +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. + +MULTILINE_CPP_IS_BRIEF = NO + +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. + +INHERIT_DOCS = YES + +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. + +SEPARATE_MEMBER_PAGES = NO + +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. + +TAB_SIZE = 7 + +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. + +ALIASES = + +# This tag can be used to specify a number of word-keyword mappings (TCL only). +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. + +TCL_SUBST = + +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_FOR_C = NO + +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. + +OPTIMIZE_OUTPUT_JAVA = NO + +# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. + +OPTIMIZE_FOR_FORTRAN = YES + +# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. + +OPTIMIZE_OUTPUT_VHDL = NO + +# Doxygen selects the parser to use depending on the extension of the files it +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make +# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C +# (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. + +EXTENSION_MAPPING = + +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable +# documentation. See http://daringfireball.net/projects/markdown/ for details. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. + +MARKDOWN_SUPPORT = YES + +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + +# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration +# diagrams that involve STL classes more complete and accurate. +# The default value is: NO. + +BUILTIN_STL_SUPPORT = NO + +# If you use Microsoft's C++/CLI language, you should set this option to YES to +# enable parsing support. +# The default value is: NO. + +CPP_CLI_SUPPORT = NO + +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. + +SIP_SUPPORT = NO + +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. + +IDL_PROPERTY_SUPPORT = NO + +# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC +# tag is set to YES, then doxygen will reuse the documentation of the first +# member in the group (if any) for the other members of the group. By default +# all members of a group must be documented explicitly. +# The default value is: NO. + +DISTRIBUTE_GROUP_DOC = NO + +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. + +SUBGROUPING = YES + +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. + +INLINE_GROUPED_CLASSES = NO + +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. + +INLINE_SIMPLE_STRUCTS = NO + +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So +# typedef struct TypeS {} TypeT, will appear in the documentation as a struct +# with name TypeT. When disabled the typedef will appear as a member of a file, +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound +# types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. + +TYPEDEF_HIDES_STRUCT = NO + +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. + +LOOKUP_CACHE_SIZE = 0 + +#--------------------------------------------------------------------------- +# Build related configuration options +#--------------------------------------------------------------------------- + +# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. + +EXTRACT_ALL = YES + +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. + +EXTRACT_PRIVATE = NO + +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. + +EXTRACT_PACKAGE = NO + +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. + +EXTRACT_STATIC = NO + +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. + +EXTRACT_LOCAL_CLASSES = YES + +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. + +EXTRACT_LOCAL_METHODS = NO + +# If this flag is set to YES, the members of anonymous namespaces will be +# extracted and appear in the documentation as a namespace called +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. + +EXTRACT_ANON_NSPACES = NO + +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_MEMBERS = NO + +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. + +HIDE_UNDOC_CLASSES = NO + +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. + +HIDE_FRIEND_COMPOUNDS = NO + +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. + +HIDE_IN_BODY_DOCS = NO + +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. + +INTERNAL_DOCS = NO + +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also +# allowed. This is useful if you have classes or files whose names only differ +# in case and if your file system supports case sensitive file names. Windows +# and Mac users are advised to set this option to NO. +# The default value is: system dependent. + +CASE_SENSE_NAMES = NO + +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. + +HIDE_SCOPE_NAMES = NO + +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. + +SHOW_INCLUDE_FILES = YES + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. + +FORCE_LOCAL_INCLUDES = NO + +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. + +INLINE_INFO = YES + +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. + +SORT_MEMBER_DOCS = YES + +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: NO. + +SORT_BRIEF_DOCS = NO + +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. + +SORT_MEMBERS_CTORS_1ST = NO + +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. + +SORT_GROUP_NAMES = NO + +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. +# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. + +SORT_BY_SCOPE_NAME = NO + +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. + +STRICT_PROTO_MATCHING = NO + +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. + +GENERATE_TODOLIST = NO + +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. + +GENERATE_TESTLIST = NO + +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. + +GENERATE_BUGLIST = NO + +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. + +GENERATE_DEPRECATEDLIST= NO + +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if <section_label> ... \endif and \cond <section_label> +# ... \endcond blocks. + +ENABLED_SECTIONS = + +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. + +MAX_INITIALIZER_LINES = 30 + +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. + +SHOW_USED_FILES = YES + +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. + +SHOW_FILES = YES + +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. + +SHOW_NAMESPACES = YES + +# The FILE_VERSION_FILTER tag can be used to specify a program or script that +# doxygen should invoke to get the current version for each file (typically from +# the version control system). Doxygen will invoke the program by executing (via +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. + +FILE_VERSION_FILTER = + +# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed +# by doxygen. The layout file controls the global structure of the generated +# output files in an output format independent way. To create the layout file +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. + +LAYOUT_FILE = + +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. Do not use file names with spaces, bibtex cannot handle them. See +# also \cite for info how to create references. + +CITE_BIB_FILES = + +#--------------------------------------------------------------------------- +# Configuration options related to warning and progress messages +#--------------------------------------------------------------------------- + +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. + +QUIET = NO + +# The WARNINGS tag can be used to turn on/off the warning messages that are +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. + +WARNINGS = YES + +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. + +WARN_IF_UNDOCUMENTED = NO + +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. + +WARN_IF_DOC_ERROR = YES + +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. + +WARN_NO_PARAMDOC = NO + +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. + +WARN_FORMAT = "$file:$line: $text" + +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). + +WARN_LOGFILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the input files +#--------------------------------------------------------------------------- + +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. + +INPUT = ../ + +# This tag can be used to specify the character encoding of the source files +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. + +INPUT_ENCODING = UTF-8 + +# If the value of the INPUT tag contains directories, you can use the +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. + +FILE_PATTERNS = *.c \ + *.cc \ + *.cxx \ + *.cpp \ + *.c++ \ + *.h \ + *.inc \ + *.f90 \ + *.f \ + *.C \ + *.CC \ + *.C++ \ + *.H \ + *.F90 \ + *.F + +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. + +RECURSIVE = YES + +# The EXCLUDE tag can be used to specify files and/or directories that should be +# excluded from the INPUT source files. This way you can easily exclude a +# subdirectory from a directory tree whose root is specified with the INPUT tag. +# +# Note that relative paths are relative to the directory from which doxygen is +# run. + +EXCLUDE = ../lapack \ + ../blas \ + ../AD \ + ../tAD \ + ../g_taf/mkTAF \ + ../TAF \ + ../tmp \ + ../models \ + ../tests \ + ./ \ + ../doc \ + ../mach \ + ../shemat_suite.bak \ + ../.UNUSED \ + ../inverse/borehole \ + ../hdf5/integer32 \ + ../hdf5/integer64 \ + ../props/fluids \ + ../simul/gs \ + ../simul/sgsim \ + ../simul/enkf \ + ../simul/visim \ + ../wrapper \ + ../refine + +# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or +# directories that are symbolic links (a Unix file system feature) are excluded +# from the input. +# The default value is: NO. + +EXCLUDE_SYMLINKS = YES + +# If the value of the INPUT tag contains directories, you can use the +# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* + +EXCLUDE_PATTERNS = */AD/* + +# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names +# (namespaces, classes, functions, etc.) that should be excluded from the +# output. The symbol name can be a fully qualified name, a word, or if the +# wildcard * is used, a substring. Examples: ANamespace, AClass, +# AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* + +EXCLUDE_SYMBOLS = + +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). + +EXAMPLE_PATH = + +# If the value of the EXAMPLE_PATH tag contains directories, you can use the +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. + +EXAMPLE_PATTERNS = * + +# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. + +EXAMPLE_RECURSIVE = NO + +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). + +IMAGE_PATH = ../doc/doc_image + +# The INPUT_FILTER tag can be used to specify a program that doxygen should +# invoke to filter for each input file. Doxygen will invoke the filter program +# by executing (via popen()) the command: +# +# <filter> <input-file> +# +# where <filter> is the value of the INPUT_FILTER tag, and <input-file> is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. + +INPUT_FILTER = + +# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. + +FILTER_PATTERNS = + +# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. + +FILTER_SOURCE_FILES = NO + +# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. + +FILTER_SOURCE_PATTERNS = + +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + +#--------------------------------------------------------------------------- +# Configuration options related to source browsing +#--------------------------------------------------------------------------- + +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. + +SOURCE_BROWSER = YES + +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. + +INLINE_SOURCES = YES + +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. + +STRIP_CODE_COMMENTS = YES + +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. + +REFERENCED_BY_RELATION = NO + +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. + +REFERENCES_RELATION = NO + +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. + +REFERENCES_LINK_SOURCE = YES + +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +USE_HTAGS = NO + +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. + +VERBATIM_HEADERS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the alphabetical class index +#--------------------------------------------------------------------------- + +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. + +ALPHABETICAL_INDEX = NO + +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +COLS_IN_ALPHA_INDEX = 5 + +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. + +IGNORE_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the HTML output +#--------------------------------------------------------------------------- + +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. + +GENERATE_HTML = YES + +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_OUTPUT = html + +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FILE_EXTENSION = .html + +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_HEADER = + +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_FOOTER = + +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_STYLESHEET = + +# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- +# defined cascading style sheet that is included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet file to the output directory. For an example +# see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + +# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the HTML output directory. Note +# that these files will be copied to the base HTML output directory. Use the +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_FILES = + +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_HUE = 220 + +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_SAT = 100 + +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_COLORSTYLE_GAMMA = 80 + +# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_TIMESTAMP = NO + +# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML +# documentation will contain sections that can be hidden and shown after the +# page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_DYNAMIC_SECTIONS = NO + +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_INDEX_NUM_ENTRIES = 100 + +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_DOCSET = NO + +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_FEEDNAME = "Doxygen generated docs" + +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_BUNDLE_ID = org.doxygen.Project + +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify +# the documentation publisher. This should be a reverse domain-name style +# string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_ID = org.doxygen.Publisher + +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. + +DOCSET_PUBLISHER_NAME = Publisher + +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_HTMLHELP = NO + +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be +# written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_FILE = + +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +HHC_LOCATION = + +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +GENERATE_CHI = NO + +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +CHM_INDEX_ENCODING = + +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +BINARY_TOC = NO + +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. + +TOC_EXPAND = NO + +# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_QHP = NO + +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QCH_FILE = + +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_NAMESPACE = org.doxygen.Project + +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_VIRTUAL_FOLDER = doc + +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_NAME = + +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_CUST_FILTER_ATTRS = + +# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHP_SECT_FILTER_ATTRS = + +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. + +QHG_LOCATION = + +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_ECLIPSEHELP = NO + +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. + +ECLIPSE_DOC_ID = org.doxygen.Project + +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +DISABLE_INDEX = NO + +# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +GENERATE_TREEVIEW = NONE + +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. + +ENUM_VALUES_PER_LINE = 4 + +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. + +TREEVIEW_WIDTH = 250 + +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +EXT_LINKS_IN_WINDOW = NO + +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_FONTSIZE = 10 + +# Use the FORMULA_TRANPARENT tag to determine whether or not the images +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +FORMULA_TRANSPARENT = YES + +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. + +USE_MATHJAX = NO + +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest + +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_EXTENSIONS = + +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use <access key> + S +# (what the <access key> is depends on the OS and browser, but it is typically +# <CTRL>, <ALT>/<option>, or both). Inside the search box use the <cursor down +# key> to jump into the search results window, the results can be navigated +# using the <cursor keys>. Press <Enter> to select an item or <escape> to cancel +# the search. The filter options can be selected when the cursor is inside the +# search box by pressing <Shift>+<cursor down>. Also here use the <cursor keys> +# to select a filter and <Enter> or <escape> to activate or cancel the filter +# option. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. + +SEARCHENGINE = YES + +# When the SERVER_BASED_SEARCH tag is enabled the search engine will be +# implemented using a web server instead of a web client using Javascript. There +# are two flavours of web server based searching depending on the +# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for +# searching and an index file used by the script. When EXTERNAL_SEARCH is +# enabled the indexing and searching needs to be provided by external tools. See +# the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SERVER_BASED_SEARCH = NO + +# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP +# script for searching. Instead the search results are written to an XML file +# which needs to be processed by an external indexer. Doxygen will invoke an +# external search engine pointed to by the SEARCHENGINE_URL option to obtain the +# search results. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). +# +# See the section "External Indexing and Searching" for details. +# The default value is: NO. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH = NO + +# The SEARCHENGINE_URL should point to a search engine hosted by a web server +# which will return the search results when EXTERNAL_SEARCH is enabled. +# +# Doxygen ships with an example indexer ( doxyindexer) and search engine +# (doxysearch.cgi) which are based on the open source search engine library +# Xapian (see: http://xapian.org/). See the section "External Indexing and +# Searching" for details. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHENGINE_URL = + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed +# search data is written to a file for indexing by an external tool. With the +# SEARCHDATA_FILE tag the name of this file can be specified. +# The default file is: searchdata.xml. +# This tag requires that the tag SEARCHENGINE is set to YES. + +SEARCHDATA_FILE = searchdata.xml + +# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the +# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is +# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple +# projects and redirect the results back to the right project. +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTERNAL_SEARCH_ID = + +# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen +# projects other than the one defined by this configuration file, but that are +# all added to the same external search index. Each project needs to have a +# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of +# to a relative location where the documentation can be found. The format is: +# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... +# This tag requires that the tag SEARCHENGINE is set to YES. + +EXTRA_SEARCH_MAPPINGS = + +#--------------------------------------------------------------------------- +# Configuration options related to the LaTeX output +#--------------------------------------------------------------------------- + +# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# The default value is: YES. + +GENERATE_LATEX = YES + +# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_OUTPUT = latex + +# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be +# invoked. +# +# Note that when enabling USE_PDFLATEX this option is only used for generating +# bitmaps for formulas in the HTML output, but not in the Makefile that is +# written to the output directory. +# The default file is: latex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_CMD_NAME = latex + +# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate +# index for LaTeX. +# The default file is: makeindex. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +MAKEINDEX_CMD_NAME = makeindex + +# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +COMPACT_LATEX = NO + +# The PAPER_TYPE tag can be used to set the paper type that is used by the +# printer. +# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x +# 14 inches) and executive (7.25 x 10.5 inches). +# The default value is: a4. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PAPER_TYPE = a4wide + +# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names +# that should be included in the LaTeX output. To get the times font for +# instance you can specify +# EXTRA_PACKAGES=times +# If left blank no extra packages will be included. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +EXTRA_PACKAGES = + +# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the +# generated LaTeX document. The header should contain everything until the first +# chapter. If it is left blank doxygen will generate a standard header. See +# section "Doxygen usage" for information on how to let doxygen write the +# default header to a separate file. +# +# Note: Only use a user-defined header if you know what you are doing! The +# following commands have a special meaning inside the header: $title, +# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will +# replace them by respectively the title of the page, the current date and time, +# only the current date, the version number of doxygen, the project name (see +# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HEADER = + +# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the +# generated LaTeX document. The footer should contain everything after the last +# chapter. If it is left blank doxygen will generate a standard footer. +# +# Note: Only use a user-defined footer if you know what you are doing! +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_FOOTER = + +# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or +# other source files which should be copied to the LATEX_OUTPUT output +# directory. Note that the files will be copied as-is; there are no commands or +# markers available. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_FILES = + +# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is +# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will +# contain links (just like the HTML output) instead of page references. This +# makes the output suitable for online browsing using a PDF viewer. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +PDF_HYPERLINKS = YES + +# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES to get a +# higher quality PDF documentation. +# The default value is: YES. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +USE_PDFLATEX = YES + +# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode +# command to the generated LaTeX files. This will instruct LaTeX to keep running +# if errors occur, instead of asking the user for help. This option is also used +# when generating formulas in HTML. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BATCHMODE = NO + +# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the +# index chapters (such as File Index, Compound Index, etc.) in the output. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_HIDE_INDICES = NO + +# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source +# code with syntax highlighting in the LaTeX output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_SOURCE_CODE = NO + +# The LATEX_BIB_STYLE tag can be used to specify the style to use for the +# bibliography, e.g. plainnat, or ieeetr. See +# http://en.wikipedia.org/wiki/BibTeX and \cite for more info. +# The default value is: plain. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_BIB_STYLE = plain + +#--------------------------------------------------------------------------- +# Configuration options related to the RTF output +#--------------------------------------------------------------------------- + +# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# RTF output is optimized for Word 97 and may not look too pretty with other RTF +# readers/editors. +# The default value is: NO. + +GENERATE_RTF = NO + +# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: rtf. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_OUTPUT = rtf + +# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# documents. This may be useful for small projects and may help to save some +# trees in general. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +COMPACT_RTF = NO + +# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will +# contain hyperlink fields. The RTF file will contain links (just like the HTML +# output) instead of page references. This makes the output suitable for online +# browsing using Word or some other Word compatible readers that support those +# fields. +# +# Note: WordPad (write) and others do not support links. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_HYPERLINKS = NO + +# Load stylesheet definitions from file. Syntax is similar to doxygen's config +# file, i.e. a series of assignments. You only have to provide replacements, +# missing definitions are set to their default value. +# +# See also section "Doxygen usage" for information on how to generate the +# default style sheet that doxygen normally uses. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_STYLESHEET_FILE = + +# Set optional variables used in the generation of an RTF document. Syntax is +# similar to doxygen's config file. A template extensions file can be generated +# using doxygen -e rtf extensionFile. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_EXTENSIONS_FILE = + +#--------------------------------------------------------------------------- +# Configuration options related to the man page output +#--------------------------------------------------------------------------- + +# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# classes and files. +# The default value is: NO. + +GENERATE_MAN = NO + +# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. A directory man3 will be created inside the directory specified by +# MAN_OUTPUT. +# The default directory is: man. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_OUTPUT = man + +# The MAN_EXTENSION tag determines the extension that is added to the generated +# man pages. In case the manual section does not start with a number, the number +# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is +# optional. +# The default value is: .3. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_EXTENSION = .3 + +# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it +# will generate one additional man file for each entity documented in the real +# man page(s). These additional files only source the real man page, but without +# them the man command would be unable to find the correct page. +# The default value is: NO. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_LINKS = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the XML output +#--------------------------------------------------------------------------- + +# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# captures the structure of the code including all documentation. +# The default value is: NO. + +GENERATE_XML = NO + +# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: xml. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_OUTPUT = xml + +# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a +# validating XML parser to check the syntax of the XML files. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_SCHEMA = + +# The XML_DTD tag can be used to specify a XML DTD, which can be used by a +# validating XML parser to check the syntax of the XML files. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_DTD = + +# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# listings (including syntax highlighting and cross-referencing information) to +# the XML output. Note that enabling this will significantly increase the size +# of the XML output. +# The default value is: YES. +# This tag requires that the tag GENERATE_XML is set to YES. + +XML_PROGRAMLISTING = YES + +#--------------------------------------------------------------------------- +# Configuration options related to the DOCBOOK output +#--------------------------------------------------------------------------- + +# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# that can be used to generate PDF. +# The default value is: NO. + +GENERATE_DOCBOOK = NO + +# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put. +# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in +# front of it. +# The default directory is: docbook. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_OUTPUT = docbook + +#--------------------------------------------------------------------------- +# Configuration options for the AutoGen Definitions output +#--------------------------------------------------------------------------- + +# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen +# Definitions (see http://autogen.sf.net) file that captures the structure of +# the code including all documentation. Note that this feature is still +# experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_AUTOGEN_DEF = NO + +#--------------------------------------------------------------------------- +# Configuration options related to the Perl module output +#--------------------------------------------------------------------------- + +# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# file that captures the structure of the code including all documentation. +# +# Note that this feature is still experimental and incomplete at the moment. +# The default value is: NO. + +GENERATE_PERLMOD = NO + +# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI +# output from the Perl module output. +# The default value is: NO. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_LATEX = NO + +# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# formatted so it can be parsed by a human reader. This is useful if you want to +# understand what is going on. On the other hand, if this tag is set to NO the +# size of the Perl module output will be much smaller and Perl will parse it +# just the same. +# The default value is: YES. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_PRETTY = YES + +# The names of the make variables in the generated doxyrules.make file are +# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful +# so different doxyrules.make files included by the same Makefile don't +# overwrite each other's variables. +# This tag requires that the tag GENERATE_PERLMOD is set to YES. + +PERLMOD_MAKEVAR_PREFIX = + +#--------------------------------------------------------------------------- +# Configuration options related to the preprocessor +#--------------------------------------------------------------------------- + +# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# C-preprocessor directives found in the sources and include files. +# The default value is: YES. + +ENABLE_PREPROCESSING = NO + +# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names +# in the source code. If set to NO only conditional compilation will be +# performed. Macro expansion can be done in a controlled way by setting +# EXPAND_ONLY_PREDEF to YES. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +MACRO_EXPANSION = NO + +# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then +# the macro expansion is limited to the macros specified with the PREDEFINED and +# EXPAND_AS_DEFINED tags. +# The default value is: NO. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_ONLY_PREDEF = NO + +# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# INCLUDE_PATH will be searched if a #include is found. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SEARCH_INCLUDES = YES + +# The INCLUDE_PATH tag can be used to specify one or more directories that +# contain include files that are not input files but should be processed by the +# preprocessor. +# This tag requires that the tag SEARCH_INCLUDES is set to YES. + +INCLUDE_PATH = + +# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard +# patterns (like *.h and *.hpp) to filter out the header-files in the +# directories. If left blank, the patterns specified with FILE_PATTERNS will be +# used. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +INCLUDE_FILE_PATTERNS = + +# The PREDEFINED tag can be used to specify one or more macro names that are +# defined before the preprocessor is started (similar to the -D option of e.g. +# gcc). The argument of the tag is a list of macros of the form: name or +# name=definition (no spaces). If the definition and the "=" are omitted, "=1" +# is assumed. To prevent a macro definition from being undefined via #undef or +# recursively expanded use the := operator instead of the = operator. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +PREDEFINED = + +# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this +# tag can be used to specify a list of macro names that should be expanded. The +# macro definition that is found in the sources will be used. Use the PREDEFINED +# tag if you want to use a different macro definition that overrules the +# definition found in the source code. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +EXPAND_AS_DEFINED = + +# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will +# remove all refrences to function-like macros that are alone on a line, have an +# all uppercase name, and do not end with a semicolon. Such function macros are +# typically used for boiler-plate code, and will confuse the parser if not +# removed. +# The default value is: YES. +# This tag requires that the tag ENABLE_PREPROCESSING is set to YES. + +SKIP_FUNCTION_MACROS = YES + +#--------------------------------------------------------------------------- +# Configuration options related to external references +#--------------------------------------------------------------------------- + +# The TAGFILES tag can be used to specify one or more tag files. For each tag +# file the location of the external documentation should be added. The format of +# a tag file without this location is as follows: +# TAGFILES = file1 file2 ... +# Adding location for the tag files is done as follows: +# TAGFILES = file1=loc1 "file2 = loc2" ... +# where loc1 and loc2 can be relative or absolute paths or URLs. See the +# section "Linking to external documentation" for more information about the use +# of tag files. +# Note: Each tag file must have an unique name (where the name does NOT include +# the path). If a tag file is not located in the directory in which doxygen is +# run, you must also specify the path to the tagfile here. + +TAGFILES = + +# When a file name is specified after GENERATE_TAGFILE, doxygen will create a +# tag file that is based on the input files it reads. See section "Linking to +# external documentation" for more information about the usage of tag files. + +GENERATE_TAGFILE = + +# If the ALLEXTERNALS tag is set to YES all external class will be listed in the +# class index. If set to NO only the inherited external classes will be listed. +# The default value is: NO. + +ALLEXTERNALS = NO + +# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in +# the modules index. If set to NO, only the current project's groups will be +# listed. +# The default value is: YES. + +EXTERNAL_GROUPS = YES + +# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# the related pages index. If set to NO, only the current project's pages will +# be listed. +# The default value is: YES. + +EXTERNAL_PAGES = YES + +# The PERL_PATH should be the absolute path and name of the perl script +# interpreter (i.e. the result of 'which perl'). +# The default file (with absolute path) is: /usr/bin/perl. + +PERL_PATH = /usr/bin/perl + +#--------------------------------------------------------------------------- +# Configuration options related to the dot tool +#--------------------------------------------------------------------------- + +# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to +# NO turns the diagrams off. Note that this option also works with HAVE_DOT +# disabled, but it is recommended to install and use dot, since it yields more +# powerful graphs. +# The default value is: YES. + +CLASS_DIAGRAMS = YES + +# You can define message sequence charts within doxygen comments using the \msc +# command. Doxygen will then run the mscgen tool (see: +# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the +# documentation. The MSCGEN_PATH tag allows you to specify the directory where +# the mscgen tool resides. If left empty the tool is assumed to be found in the +# default search path. + +MSCGEN_PATH = + +# If set to YES, the inheritance and collaboration graphs will hide inheritance +# and usage relations if the target is undocumented or is not a class. +# The default value is: YES. + +HIDE_UNDOC_RELATIONS = YES + +# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is +# available from the path. This tool is part of Graphviz (see: +# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent +# Bell Labs. The other options in this section have no effect if this option is +# set to NO +# The default value is: NO. + +HAVE_DOT = YES + +# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed +# to run in parallel. When set to 0 doxygen will base this on the number of +# processors available in the system. You can set it explicitly to a value +# larger than 0 to get control over the balance between CPU load and processing +# speed. +# Minimum value: 0, maximum value: 32, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_NUM_THREADS = 0 + +# When you want a differently looking font n the dot files that doxygen +# generates you can specify the font name using DOT_FONTNAME. You need to make +# sure dot is able to find the font, which can be done by putting it in a +# standard location or by setting the DOTFONTPATH environment variable or by +# setting DOT_FONTPATH to the directory containing the font. +# The default value is: Helvetica. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTNAME = Helvetica + +# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of +# dot graphs. +# Minimum value: 4, maximum value: 24, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTSIZE = 10 + +# By default doxygen will tell dot to use the default font as specified with +# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set +# the path where dot can find it using this tag. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_FONTPATH = + +# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for +# each documented class showing the direct and indirect inheritance relations. +# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +CLASS_GRAPH = YES + +# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a +# graph for each documented class showing the direct and indirect implementation +# dependencies (inheritance, containment, and class references variables) of the +# class with other documented classes. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +COLLABORATION_GRAPH = YES + +# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for +# groups, showing the direct groups dependencies. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GROUP_GRAPHS = YES + +# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# collaboration diagrams in a style similar to the OMG's Unified Modeling +# Language. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LOOK = NO + +# If the UML_LOOK tag is enabled, the fields and methods are shown inside the +# class node. If there are many fields or methods and many nodes the graph may +# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the +# number of items for each type to make the size more manageable. Set this to 0 +# for no limit. Note that the threshold may be exceeded by 50% before the limit +# is enforced. So when you set the threshold to 10, up to 15 fields may appear, +# but if the number exceeds 15, the total amount of fields shown is limited to +# 10. +# Minimum value: 0, maximum value: 100, default value: 10. +# This tag requires that the tag HAVE_DOT is set to YES. + +UML_LIMIT_NUM_FIELDS = 10 + +# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and +# collaboration graphs will show the relations between templates and their +# instances. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +TEMPLATE_RELATIONS = NO + +# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to +# YES then doxygen will generate a graph for each documented file showing the +# direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDE_GRAPH = YES + +# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are +# set to YES then doxygen will generate a graph for each documented file showing +# the direct and indirect include dependencies of the file with other documented +# files. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +INCLUDED_BY_GRAPH = YES + +# If the CALL_GRAPH tag is set to YES then doxygen will generate a call +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable call graphs for selected +# functions only using the \callgraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALL_GRAPH = YES + +# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller +# dependency graph for every global function or class method. +# +# Note that enabling this option will significantly increase the time of a run. +# So in most cases it will be better to enable caller graphs for selected +# functions only using the \callergraph command. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +CALLER_GRAPH = YES + +# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical +# hierarchy of all classes instead of a textual one. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GRAPHICAL_HIERARCHY = YES + +# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the +# dependencies a directory has on other directories in a graphical way. The +# dependency relations are determined by the #include relations between the +# files in the directories. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DIRECTORY_GRAPH = YES + +# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images +# generated by dot. +# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order +# to make the SVG files visible in IE 9+ (other browsers do not have this +# requirement). +# Possible values are: png, jpg, gif and svg. +# The default value is: png. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_IMAGE_FORMAT = png + +# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to +# enable generation of interactive SVG images that allow zooming and panning. +# +# Note that this requires a modern browser other than Internet Explorer. Tested +# and working are Firefox, Chrome, Safari, and Opera. +# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make +# the SVG files visible. Older versions of IE do not have SVG support. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +INTERACTIVE_SVG = NO + +# The DOT_PATH tag can be used to specify the path where the dot tool can be +# found. If left blank, it is assumed the dot tool can be found in the path. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_PATH = + +# The DOTFILE_DIRS tag can be used to specify one or more directories that +# contain dot files that are included in the documentation (see the \dotfile +# command). +# This tag requires that the tag HAVE_DOT is set to YES. + +DOTFILE_DIRS = + +# The MSCFILE_DIRS tag can be used to specify one or more directories that +# contain msc files that are included in the documentation (see the \mscfile +# command). + +MSCFILE_DIRS = + +# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes +# that will be shown in the graph. If the number of nodes in a graph becomes +# larger than this value, doxygen will truncate the graph, which is visualized +# by representing a node as a red box. Note that doxygen if the number of direct +# children of the root node in a graph is already larger than +# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that +# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH. +# Minimum value: 0, maximum value: 10000, default value: 50. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_GRAPH_MAX_NODES = 100 + +# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs +# generated by dot. A depth value of 3 means that only nodes reachable from the +# root by following a path via at most 3 edges will be shown. Nodes that lay +# further from the root node will be omitted. Note that setting this option to 1 +# or 2 may greatly reduce the computation time needed for large code bases. Also +# note that the size of a graph can be further restricted by +# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction. +# Minimum value: 0, maximum value: 1000, default value: 0. +# This tag requires that the tag HAVE_DOT is set to YES. + +MAX_DOT_GRAPH_DEPTH = 5 + +# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent +# background. This is disabled by default, because dot on Windows does not seem +# to support this out of the box. +# +# Warning: Depending on the platform used, enabling this option may lead to +# badly anti-aliased labels on the edges of a graph (i.e. they become hard to +# read). +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_TRANSPARENT = NO + +# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# files in one run (i.e. multiple -o and -T options on the command line). This +# makes dot run faster, but since only newer versions of dot (>1.8.10) support +# this, this feature is disabled by default. +# The default value is: NO. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_MULTI_TARGETS = YES + +# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page +# explaining the meaning of the various boxes and arrows in the dot generated +# graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +GENERATE_LEGEND = YES + +# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# files that are used to generate the various graphs. +# The default value is: YES. +# This tag requires that the tag HAVE_DOT is set to YES. + +DOT_CLEANUP = YES diff --git a/doc/doc_image/cube.png b/doc/doc_image/cube.png new file mode 100644 index 0000000000000000000000000000000000000000..e9e570bb2b70f4922200cf8b19171e2b3a14e50e GIT binary patch literal 4345 zcmeAS@N?(olHy`uVBq!ia0y~yU@T-{U^v9V#K6E{a3*yQ0|NtNage(c!@6@aFBupZ zI14-?iy0WWg+Z8+Vb&Z81_lQ95>H=O_FG(h{N^Gd^H1_KFfhnwhD4M&=jZ08=9Msj zfOAo5Vo7R>LV0FMhJw4NZ$OG(Dmw#%K$546V@SoVw{ve#d%c3sbu!Pt|I>flglzY3 zOHO9o#TeXQy}agN(k2y$J^z0`pD*6#oA>_v?=SimWjD4jc)9Uw15+f^TW8^f>PKwG zo1BF2R4O{l$cr><N-#Zn=&!)-bI{<d0NYKb;0f2Ze3;G89&Dha?B3Ct;I;hu&mZi? zT-v5@zWYApwmLf7^n%LfzqL;%<{#m*nsI4O(beS48a>Ws{rrZ0(`>pbHu>+2SX}bs z!b(=T!ov#FcvUBT^H<U>FPM6@q)Udy#WtH`^7NeCed}^IR=;Ll5L|HoRQz2}i6@>S z?oqe@yqmmKR$7HWto(F=U#`{kKXZc|kEl&oR9;(K^TK<s(L1)_EpJsL-a7p-{jO?m z`YWIN&$5sJjmD1&@!8(b+B#Eo*-meoTJPQT>hk|bWq}%!<sXml|NHM?r{nFq@7`kO zzSUFjHcVoCvf#*;%HP+H&a3-x`=_RSt;)`OD))bxKi}c^M)~=R#VX4V_=^NA$}oE5 z=XoV&Rl!P~mrup!%2!SjQ=MuUJkjg@_voVTzALwr?r6TQtbD3n_WmV<#!1GttW!?8 z)-9g5Tb{oyRykhra7yLHq+B6!ai*oe`=SpX&7GM2pggno_<O(VqzQNbJ?qonzAo`% zO;n<vqJR7=zOpAuN7b+Imh+kuofa^Ag~EZVFQLz;u*S%J(zJBm{c+Dqv4AZp-zF{W zojptXP3A7yuUppWsr%YoPIRq!e4tOnLa<nT?z%?NuWJvKJ0A2h*(svtzRJ~*#rtW3 zukj1j%}y5=bzU=@JoVG(vgrJGVF!=1Sw~Iuv+dLl$;xAqyuZwTivPqMu7c#{k9Z1S zYhT&_o$2a<Kjxo8Z>`l-<DIVlN&CvfM~jQEHY&ZDy7b@T%Sulj&aP*g5@J=;Xt4Y} zzx>ZnKl)cb@eIB)$9HOkP0-9m%s(_l5-*>h8qK-fGyB4qT{o*PKM~a`3d+{{d*0bE zd2{QX-OSt1r`sAoH7tHO!OK8(*B`6p=l}n1-<)G`djBq$Pd7wU{^uRzESY^=eM*k- z#E|NVd-4?ms!F<kZJ1L~-&<gxown)BreiMinlpZJJ&s$o>BrK4dZLkqRa;MY_lOj1 zi0!!XaY0vbq2=7_GVYV#`t5IcOi<EnddwiQc6M3&+hq=d@7gqP%E(Sxv)1=c*{?0{ zYIf@6J#bj$%@dk5^Zp_3hjU-=ad)gcZO7I;X^Y9ncu9eMr61mXZ#KF!*`;x^wbRU- zo0DQ)I~gYm%&IWk{W7TbXy>2%!SkP-HMMI_zIDFTe(wa$qc^WRp1kEL+-};qYsIf= zoYQCXy!zO&c}3@<lZCP;eV1<ZKkgZIGSevY=Bq7<eVGl(U-Wznk89RHoLTIt>L>ry zsqn+6ty?>9JDohE8L_yv{-)NXKkK5aP2csDvvnPfT6H{I>||_u%$o$;l&${`q%+wq z`J2wtbxMu-;Z>)MPrGI+78yLPIdx@{%0sQ+e@wPBdujQF{`(M7oBu_rd1BxHP4749 z2IxKiw!8LRQfh9z*tfj$o+rtssn?>v&p2`3U;{(f%aZr1VOO%Zp1H(+zyEghllJg4 z+Ce&LD}AOr^;J)`;WepPu~<dUWUi`={^KjN3?==wUZ*{({dW1!|7<hQ#V@<AXPI7p zz$(hU`1mv5H+kyewrfk|{&dtX-)BBGTf&AZFrw$?!WD1t>vp*w`Fgiwv%vFDfp@i* zJejX(w)gJR<K}ClHr$xIhG|Ne<+Mt{Wal@^H8TqnZMr7}Uevjp$`ZU#rE+W5ZuWP~ zUO84~oqm=4V%sF`ckY^Wx5lUD-rbG=R3`0O`1sSRtzQo{K8g_wp03uP>G+!c@~Ym1 z=gfQ&nF(In<$BgBx3ZK)%Vj*b^-e!ixWLn+GWPCTtGk~fR|l<m{->`vZ^frsbA2{m zm=hf0Q9Z>^xp%VTY!~0FkvV_3`wMCx$-bT(9sPfg&_5B^@`*Nue>b+w-I*MA$z;vc zcoi*X@qIfrMSZm%ZS34;=Wy}TkFQ%RyYi(XAMg6jk)3F}FK3bFl4G%NUM=KVdD+h6 z>dDkXy;ac%vTZr07V4d;o)lKw7;kpvTV?v1;8lk&zWo!hd(z>br<e0J?cQN}L1#+f z`}w}AzuB$bCMmb;ERzs<yv)w^&+464T;I!?kLDWBvgs`RuJ^Q6lK;or?%lKB{j2`i z$#uW_(aEINf9t3HeCqAKO#j0V@u}C^H2oePUf>_{&*rdXn%gfAL5;G~520E)?L3@r z*>|qa*mQ%<X=-NciUSw^Tigq|-LZAu<gC~?C)V`d4tHK&F=yGHAc>^fr#7FSOs!t{ z_rc_desk5?@<*cH+}stIAsp6T{=s8+$(rTH%e%_;xOdO^lpQ~J5y$(R>idmCM6R7Z z@j^?aa-DAUHx;#=(+a#-)QcO%YA)Y>%)Gzj@+<pSCY3+miG1`qUMBu)dq%;tNu>=+ zB_dOEm)(>|F)3BeH>`9neG?{sg=uBjrmHI#?!FN}U$eM(?=pv#-+TL3rTQj**rVj} z?@8I`kJ?|GKAd^B@2ALD-;BWKpzU^t{`@_gxXRFm_2bFQuFDy^oZrql`2EqB8!hL` z7>??7e=IND9`x#k$a24XR?oA(*c?(`BVc-Y=bgLZ*-NLsyq;cr%EWQ&HLp{LFN$*W z2=A}plUP1^_GVYkH{T5<>n}YDE&3CxopkMljQzeJADK@o*x&7%=i+lS%qiUK<=Q3J z+3qjRpS5TAm1TPr&UxHj?|33BSJnG<+7<uKo~ke|iP>$w+b{7dW)@v$j99%vGy9%U z?``*BsoacvVOMnSGim)6`m8V2pn17OOGVM4bLqAV%q!;`sf0e!U9hNHkjdKp+Qazx zN&ERNx|2iKT)1thJnPQYiQI1rzh2z<;$EiqnllnRRpuKV_@sUL_?&a?=gm$}*vicD z=}gax``f=>-BkPWd;PZ`AzZJ6<CgFn>Im<@@-*vm|3yuSBz0MRmD-A%rujFLE*gpH z+1BiN6u7EHpI5&tw=wefoNH`Om$tYCop?Us^OJLKZ<<#qK00uvVNs0v{Du6Q?LDtv ztO$Jn`|g#l*$F3?`v^D*uUf;kjOQ!YmCqIis;(Brk=49?Ix??$FS&@%+BNT()h(BT zl~+<W+BvbzR!v+e*R$H5)9UEg-&YqFgj+rNl(Oe#U)JFu#-n*#S1|>9{9tGEUC(*G z@lH(%C%aeb8mHw6>6Xc|TGebnzc&6YEcShxsB$WByW!+3eW8D>rhZF5dwbR+)!F8! z=RV(*ynWeZtE`W;?UUCxI<sn(-%)(HBGR7qwB?~cyw`7@2zt4<{=cc6?xkB9vd;}e z{Zh}xEIx4S)B^T|Jj2$!f+z34JLyLyoV~rx;pcAGz#5AJ<G^P}*S#*2uTMPk$o8($ z2EN3X)iED7uKFWs&%krP<E`n#!o0v7g$QGD-@5)cc26~}6E^xEvU@%|?M1Wei>6(S zmfl((EC~-C47+&kmF=#t+SE5`T1_3#?C^y*uALQUN{a4#;u(?T`RMG^`(G|!G_fpq zPP(z}V6s-!)OXvY12rzB#PuI6;7^@<iRI<#m0r8pw-x^|whoXx{Imb=S&g5L7urw$ zPGR?AYn+r9UnILrM!hF-S<ul+!MS^s#k<*<G$hP+-{Q5t|9s+Z2G-kJ>k11hUQd;r zTADs-tDyX4aW)N!X_C?VEiat*mG*V}JB9O3(`4q2(+@s7@cx!nm(_xZJ!VR*(f4+3 zUR$f&veM?_+f{RNyArLBS-Up~?`hw_d29#M+XhvZuCKc;_j_$$_∋j>E>fw5>H< z5eGNyY`8RwU+CYw8m_jts{?eFF!&tY@Uvmks}JWdFWzK#^p54L|9)pWW@=5D{`+3) z456NHyQeZar2D5ViM^w-K7u1y=;g8ZuD$yUEOi$zxe<EK&aA?5{^eyCHLX8A{nFo_ zekEM1{<rFdo0j)DLu_4NUo5=oSZ4FDGiB=~b6>gdQ|IlIdb)%8tDi^!+rr|X+f(N# zm;dk3S4+9}vLd)MI+!=zs#0msryox)K8-!q^R`ueWx?|bp3ZL*p9_}Bg{!>(eRnc* zqmv!$?8Ud|?5XUniv4tO&$^c)nb8Z~esqLxsd+8EcaBL1C!-0g`xDXg@6tZjF`wrV zvWV?{&3a6JyFhbU#wX##{5LoDDybjc!QU=3F;Uz{@OOe?^6wq~@o`T!t@h@twtV=~ zQ13HiW7WfbD=OS8@1=_gcCTHP@q{yQ``hBri()R`aPCO_&2-d>SHrl~=agEq;I_7K zpMcj53LJ;c<kLE8&)D1a9(cY_gyZhMg+@m&w=7v!{nCInvQKcX@0D|F#WN4xcYkgB z^Tx7cR^o3gR1AI=3;jNznIlzM#Gv|ld$XqD+?j3<l=am7*UWIrKPbfa{`85-0-d+C zI=JQwJl_30=h6qqUHW^H_Vc$bU0lHCR{lJDhWD`zZ(ZVp6Lm|t+{%^iNnT=fT5u<p zaan?dO(^rJZqs}V!?yyDJ};j+J+<LeQZ3itcyABmbv|DTckiE`lC*n;y|!MH!-Bc9 zOB^3Ko8?xC{1ckn<ajcnbGuMLTv>YC!$gUO2?00ckFO2%fBo3-eY0ZOwff-mIpQ17 zZ#s4D>{`y6C$Z)!&JQ>OtmL+?xgKqxqyExK?xdu~5jzPnPLazKQfgRz@5>(&={c}` z^J&wm+&i+D@~E@Fvg7obd9u0FJUwL{tHrAm8|K|?)D-4<KmB>Wo!q<KardJiH`dz4 zJl*nAW7dHwE`C4HPCRw<K%@H~tA+&Lyfz&h&gUFHo$pK44U2xntG?P7a*@4xk(J8B z8?nt6TYM5Ou`Kg>&?I#5&+qrgC;WIF_vPDG<*joZ8Z{*!UJ{%T|L@s5B}uNi_l|OB z>Ras2`dni$!-z5dms;&Rg;Gg}lY2jWdHkNen&-;}HAVkNcm5fqs_n~gT-7IGsla#d z>iWlbq_?_wEuG5rbCQgP0jr<pkEFlTC%vAtqgbU=r|R?%wt82~YpWcB&%Qq(qGNRN zg5XM9yY%3wszxmtp#>=w)-#y+E<F`*Ss!`RZu32z856UbHG|zGwQBvJTD=N6buCb~ z%%CMDNR8=K_b*L}U)loewcgKL`!#_pc6#|7i&vgM_8FvJTjKmCd4uPz<;ni+A~QA# z&Mx{TpA*HSVbFST!U6T5ce<6=q<jt<xN!O03@YRi(+-p2=Zs+B@=^S7(<EwUpF;ob z#h<oIWZyGzFjykX7QHw#`;mw)fAF&x(|BIqcC)%HxshKa`r*W9sp~E}zA#{QUa}w{ zjDgGN;DuMt*X~}O?G<{~bkPBkGb_a-H)o1n+A6khw%?*ji&g(bGWuVu^=FOvdD?DK z@B}vA@C#DMLSJkP{qp7C`7#DBE7plZ-&AJ%{Cd+YRKm55Pib-4qpSCmv~!#MZmwfr zCUsJGp33>#rI&MO)=2u?JS4=X<Ne6)ZRKJE*4b+D4{Q$IpIbR&VJ*X{{cjJPn7n+x z&tI{%`l5AH+P%1K=Dpsv@R9TKCvP`4<}ELJ=l<jHZqo;=w39AscK3X6yLYnb*F?4} zR!cJ5+gz7BXiHt#w*9?X&S4Rr&5uscb7aWAXYl5XxRPuM*S1-vp&=%rdbJrhEPXxu zu7!rn-!scMTk^<YqqoOrlb6qGxt1+q6R=HL$F{`$;1t=;&0BT0tMJ8gE=ypLT5v#w z=k#%LtBczW-!~`zy<KKd!qrxKYT9m2>#7SU|FKWBtkR13Io}L44B_eO=d#Wzp$Pz7 CtX9YX literal 0 HcmV?d00001 diff --git a/forward/alloc_arrays.f90 b/forward/alloc_arrays.f90 new file mode 100644 index 0000000..251d8a0 --- /dev/null +++ b/forward/alloc_arrays.f90 @@ -0,0 +1,423 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief allocate all global main arrays (dynamic size) +!> @param[in] ismpl local sample index +!> @details +!> an additional ccNUMA initialisation is performed after the allocation,\n +!> see "numa_init"\n + SUBROUTINE alloc_arrays(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_conc + use mod_blocking_size + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i + INCLUDE 'OMP_TOOLS.inc' + INTEGER l2 +! thread stuff + ! INTEGER tpos, tanz + INTEGER mfactor +! only for benchmarking +#ifdef BENCH + DOUBLE PRECISION trun, tend +#endif + +! + IF (linfos(1)>=2) WRITE(*,*) ' [I] : ... alloc_arrays' +#ifdef BENCH + CALL sys_cputime(trun) +#endif + +! single system size (factor == 1) + mfactor = 1 + + ALLOCATE(project_sfx(nsmpl)) + DO i = 1, nsmpl + project_sfx(i) = '' + END DO + + ALLOCATE(propunit(nunits,nprop,nsmpl)) + memory = memory + nunits*nprop*nsmpl + CALL set_dval(nunits*nprop*nsmpl,0.D0,propunit) + +! temporary convergence list + ALLOCATE(conc_conv(ntrac,nsmpl)) + memory = memory + ntrac*nsmpl + + ALLOCATE(node_info(i0,j0,k0)) + memory = memory + i0*j0*k0 +! additional global & private vectors for linear system solver +! global buffer for boundary exchange (+ismpl) + ALLOCATE(lss_bound_block(block_i*block_j+block_i*block_k+ block_j*block_k,bdim_i,bdim_j,bdim_k,2,nsmpl)) + memory = memory + (block_i*block_j+block_i*block_k+block_j*block_k)*bdim_i*bdim_j*bdim_k*2*nsmpl + ALLOCATE(lss_dnrm(i0*j0*k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(lss_tmp(i0*j0*k0,nsmpl)) + memory = memory + i0*j0*k0*nsmpl +! private copy for preconditioning (+Tlevel_1 +ismpl) + ALLOCATE(lss_lma(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lmb(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lmc(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lmd(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lme(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lmf(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lmg(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lud(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lx(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_lb(max_blocks*block_i*block_j*block_k,tlevel_1, nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl +! + ALLOCATE(lss_lloctmp(max_blocks*block_i*block_j*block_k, max_loctmp,tlevel_1,nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*max_loctmp*tlevel_1*nsmpl +! + ALLOCATE(lss_ldnrm(max_blocks*block_i*block_j*block_k, tlevel_1,nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + ALLOCATE(lss_ud_block(block_i*block_j+block_i*block_k+ block_j*block_k,max_blocks,tlevel_1,nsmpl)) + memory = memory + (block_i*block_j+block_i*block_k+block_j*block_k)*max_blocks*tlevel_1*nsmpl + ALLOCATE(lss_lr0_hat(max_blocks*block_i*block_j*block_k, tlevel_1,nsmpl)) + memory = memory + max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl +! sanity check + IF (max_blocks*block_i*block_j*block_k*tlevel_1<i0*j0*k0*mfactor) THEN +! when fewer than I0*J0*K0 memory is allocated, +! then we have lost some elements in "par_init2(I0,J0,K0)" + WRITE(*,'(1A)') 'error: software bug, something goes wrong in "alloc_arrays"!' + STOP + END IF + +! +! variables for variable time stepping + allocate(flag_delt(nsmpl)) + memory = memory + nsmpl + ALLOCATE(delt_count(nsmpl)) + memory = memory + nsmpl + allocate(flag_1st_timestep(nsmpl)) + memory = memory + nsmpl + allocate(delt_old(nsmpl)) + memory = memory + nsmpl +! + +! +! coefficients for linear equations + ALLOCATE(a(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(b(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(c(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(d(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(e(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(f(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + ALLOCATE(g(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl +! formerly the solution vector - linear system, now a temporary helper vector + ALLOCATE(x(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl +! only for ilu-precond. (shadow vectors) + ALLOCATE(ud(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl +! rhs + ALLOCATE(w(i0,j0,k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl +! r0_hat for BiCGstab + ALLOCATE(r(i0,j0,k0*mfactor)) + memory = memory + i0*j0*k0*mfactor +! Dirichlet mask for special diagonal preconditioning + ALLOCATE(bc_mask(i0*j0*k0*mfactor,nsmpl)) + memory = memory + i0*j0*k0*mfactor*nsmpl + +! state variables + ALLOCATE(head(i0,j0,k0,nsmpl)) + memory = memory + i0*j0*k0*nsmpl + ALLOCATE(temp(i0,j0,k0,nsmpl)) + memory = memory + i0*j0*k0*nsmpl + ALLOCATE(conc(i0,j0,k0,max(ntrans,1),nsmpl)) + memory = memory + i0*j0*k0*max(ntrans,1)*nsmpl + ALLOCATE(pres(i0,j0,k0,nsmpl)) + memory = memory + i0*j0*k0*nsmpl + ALLOCATE(tsal(i0,j0,k0,nsmpl)) + memory = memory + i0*j0*k0*nsmpl + +! uindex(allocated in read_model) +! memory = memory + i0*j0*k0 + +! inverse + ALLOCATE(headold(i0*j0*k0,ncgen,nsmpl)) + memory = memory + i0*j0*k0*ncgen*nsmpl + ALLOCATE(tempold(i0*j0*k0,ncgen,nsmpl)) + memory = memory + i0*j0*k0*ncgen*nsmpl + ALLOCATE(concold(i0*j0*k0,max(ntrans,1),ncgen,nsmpl)) + memory = memory + i0*j0*k0*ncgen*nsmpl*max(ntrans,1) + ALLOCATE(presold(i0*j0*k0,ncgen,nsmpl)) + memory = memory + i0*j0*k0*ncgen*nsmpl + + ALLOCATE(delx(i0)) + memory = memory + i0 + ALLOCATE(dely(j0)) + memory = memory + j0 + ALLOCATE(delz(k0)) + memory = memory + k0 + ALLOCATE(delxa(i0)) + memory = memory + i0 + ALLOCATE(delya(j0)) + memory = memory + j0 + ALLOCATE(delza(k0)) + memory = memory + k0 + +! time periods - dummy - + ALLOCATE(bcperiod(ngsmax,3,max(nbctp,1),nsmpl)) + memory = memory + ngsmax*3*max(nbctp,1)*nsmpl + ALLOCATE(ibcperiod(max(nbctp,1))) + memory = memory + max(nbctp,1) + ALLOCATE(lbcperiod(ngsmax,max(nbctp,1))) + memory = memory + ngsmax*max(nbctp,1) + ALLOCATE(outt(1)) + memory = memory + 1 + + ALLOCATE(smon_idx(nsmpl)) + memory = memory + nsmpl + CALL set_ival(nsmpl,0,smon_idx) + + ! dummy allocation + allocate(delta_time(1)) + memory = memory + 1 + + ALLOCATE(simtime(nsmpl)) + memory = memory + nsmpl + + allocate(tr_switch(nsmpl)) + memory = memory + nsmpl + do i = 1, nsmpl + tr_switch(i) = .true. + end do + + ALLOCATE(fh_table(c_fhandler,tlevel_0)) + memory = memory + c_fhandler*tlevel_0 + +! reset file handler table + CALL omp_new_file_handler(l2,0) + + ALLOCATE(diff_c(max(ntrans,1))) + memory = memory + max(ntrans,1) + ALLOCATE(mmas_c(max(ntrans,1))) + memory = memory + max(ntrans,1) + ALLOCATE(beta_c(max(ntrans,1))) + memory = memory + max(ntrans,1) + +! boundary structures + ALLOCATE(ibc_data(max(nbc_data,1),nibc)) + memory = memory + max(nbc_data,1)*nibc + ALLOCATE(dbc_data(max(nbc_data,1),ndbc,nsmpl)) + memory = memory + max(nbc_data,1)*ndbc*nsmpl + ALLOCATE(dbc_dataold(max(nbc_data,1))) + memory = memory + max(nbc_data,1) + +! borehole logs + ALLOCATE(ibh_pos(2,nbh_logs)) + memory = memory + 2*nbh_logs + ALLOCATE(cbh_name(nbh_logs)) + memory = memory + nbh_logs*64 + +! - convergency history buffer - + ALLOCATE(conv_history(conv_hlen,conv_hmax,nsmpl)) + memory = memory + conv_hlen*conv_hmax*nsmpl + ALLOCATE(conv_chlen(conv_hmax,nsmpl)) + ALLOCATE(conv_ipos(conv_hmax,nsmpl)) + ALLOCATE(lcon(conv_hmax,nsmpl)) + memory = memory + 3*conv_hmax*nsmpl + +! OpenMP specific REDUCTION stuff + ALLOCATE(omp_dglobal(tlevel_1,9,nsmpl)) + ALLOCATE(omp_iglobal(tlevel_1,3,nsmpl)) + memory = memory + 12*tlevel_1*nsmpl + +#ifdef BENCH + CALL sys_cputime(tend) + WRITE(*,'(1A,1F8.2,1A)') & + ' [I] : memory allocation time (serial) =', tend - trun, & + ' sec' + trun = tend +#endif + +! initialisation of this kind, is needfull for NUMA architectures !!! +! ----------- NUMA ------------- + DO l2 = 1, nsmpl +! Tlevel_0 = 1 !!! + CALL numa_init(mfactor,l2) + END DO +! ----------- NUMA ------------- + +#ifdef BENCH + CALL sys_cputime(tend) + WRITE(*,'(1A,1F8.2,1A)') & + ' [I] : memory allocation time (parallel) =', tend - trun, & + ' sec' +#endif + + + ALLOCATE(sdata(1,nsmpl)) + memory = memory + nsmpl + + RETURN + END SUBROUTINE alloc_arrays + +!> @brief initialisation of this kind, is needfull for NUMA architectures !!! +!> @param[in] mfactor multiply factor for multi-phase methods +!> @param[in] ismpl local sample index + SUBROUTINE numa_init(mfactor,ismpl) + use arrays + use mod_genrl + use mod_data + use mod_conc + use mod_time + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + INCLUDE 'OMP_TOOLS.inc' + INTRINSIC dble +! thread stuff + INTEGER tpos, tanz, l2, loc_mem, t_id, mfactor + + +! ----------- NUMA ------------- +!$OMP parallel default(none) private(tpos,tanz,i,j,k,l,l2,loc_mem,t_id)& +!$OMP num_threads(Tlevel_1)& +!$OMP shared(a,b,c,d,e,f,g,w,x,head,temp,pres,r,I0,J0,K0)& +!$OMP shared(ismpl,conc,concold,tsal,ntrans)& +!$OMP shared(headold,tempold,presold)& +!$OMP shared(ud,ntrac,Tlevel_1,mfactor)& +!$OMP shared(lss_bound_block,lss_dnrm,lss_tmp,lss_lUD,lss_lx,lss_lb)& +!$OMP shared(lss_lMA,lss_lMB,lss_lMC,lss_lMD,lss_lME,lss_lMF,lss_lMG)& +!$OMP shared(lss_llocTMP,lss_ldnrm,lss_ud_block,lss_lr0_hat)& +!$OMP shared(max_blocks,block_i,block_j,block_k,bdim_i,bdim_j,bdim_k) +!$ call omp_binding(ismpl) +! init + t_id = omp_get_his_thread_num() + 1 + CALL omp_part(i0*j0*k0,tpos,tanz) + CALL ijk_m(tpos,i,j,k) + loc_mem = max_blocks*block_i*block_j*block_k +! + l2 = (block_i*block_j+block_i*block_k+block_j*block_k)*bdim_i*bdim_j*bdim_k*2 + CALL set_dval(l2,0.D0,lss_bound_block(1,1,1,1,1,ismpl)) +! + CALL set_dval(tanz,0.D0,lss_tmp(tpos,ismpl)) +! + CALL set_dval(loc_mem,0.D0,lss_lma(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lmb(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lmc(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lmd(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lme(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lmf(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lmg(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lud(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lx(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lb(1,t_id,ismpl)) + CALL set_dval(loc_mem*max_loctmp,0.D0,lss_lloctmp(1,1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_ldnrm(1,t_id,ismpl)) + CALL set_dval(loc_mem,0.D0,lss_lr0_hat(1,t_id,ismpl)) + l2 = (block_i*block_j+block_i*block_k+block_j*block_k)*max_blocks + CALL set_dval(l2,0.D0,lss_ud_block(1,1,t_id,ismpl)) +! + DO l = 0, mfactor-1 + CALL set_dval(tanz,0.D0,lss_dnrm(tpos+l*I0*J0*K0,ismpl)) + CALL set_dval(tanz,0.D0,a(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,b(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,c(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,d(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,e(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,f(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,g(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,w(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,x(i,j,k+l*K0,ismpl)) + CALL set_dval(tanz,0.D0,ud(i,j,k+l*K0,ismpl)) + END DO +! + CALL set_dval(tanz,0.D0,head(i,j,k,ismpl)) + CALL set_dval(tanz,10.0D0,temp(i,j,k,ismpl)) + CALL set_dval(tanz,0.D0,pres(i,j,k,ismpl)) + DO l = 1, max(ntrans,1) + CALL set_dval(tanz,0.D0,conc(i,j,k,l,ismpl)) + END DO + CALL set_dval(tanz,0.D0,tsal(i,j,k,ismpl)) + + DO l = 1, ncgen + CALL set_dval(tanz,100.0D0,headold(tpos,l,ismpl)) + END DO + DO l = 1, ncgen + CALL set_dval(tanz,20.0D0,tempold(tpos,l,ismpl)) + END DO + DO l = 1, ncgen + CALL set_dval(tanz,1.5D7,presold(tpos,l,ismpl)) + END DO + DO l = 1, ncgen + DO l2 = 1, max(ntrans,1) + CALL set_dval(tanz,0.D0,concold(tpos,l2,l,ismpl)) + END DO + END DO +! independent of nsmpl + IF (ismpl==1) THEN +! [flow,temp,conc*] + DO l = 1, mfactor + CALL set_dval(tanz,0.D0,r(i,j,k+(l-1)*k0)) + END DO +!$OMP barrier +!$OMP do + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 +! random vector needed for BiCGStab lineare solver +! later can be initialised from a real random-number-generator + r(i,j,k) = 1.0D3/dble(0.25D0+i0/2-i+j0/2-j+k0/2-k) +! [flow,temp,conc*], [pres] + DO l = 2, mfactor + r(i,j,k+(l-1)*k0) = r(i,j,k+(l-2)*k0)*0.1D0 + END DO + END DO + END DO + END DO +!$OMP end do + END IF +!$OMP end parallel +! ----------- NUMA ------------- + RETURN + END SUBROUTINE numa_init diff --git a/forward/alloc_data.f90 b/forward/alloc_data.f90 new file mode 100644 index 0000000..5fd52cd --- /dev/null +++ b/forward/alloc_data.f90 @@ -0,0 +1,87 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief allocate data arrays (dynamic size) +!> @param[in] ismpl local sample index +!> @details + SUBROUTINE alloc_data(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_linfos + IMPLICIT NONE + integer :: ismpl + INTRINSIC max + + IF (linfos(1)>=2) THEN + WRITE(*,*) ' ' + WRITE(*,*) ' [I] : ... alloc_data' + WRITE(*,*) ' ' + END IF +! + IF (ndata>=1) THEN + ALLOCATE(ddata(ndata,n_ddata)) + memory = memory + ndata*n_ddata + ALLOCATE(idata(ndata,n_idata)) + memory = memory + ndata*n_idata + END IF +! + DEALLOCATE(sdata) + memory = memory - nsmpl + ALLOCATE(sdata(max(ndata,1),nsmpl)) + memory = memory + max(ndata,1)*nsmpl +! + RETURN + END SUBROUTINE alloc_data + + +!> @brief free data arrays (with dynamic size) +!> @param[in] ismpl local sample index +!> @details + SUBROUTINE dealloc_data(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_linfos + IMPLICIT NONE + integer :: ismpl + INTRINSIC max + + IF (linfos(1)>=2) THEN + WRITE(*,*) ' ' + WRITE(*,*) ' [I] : ... dealloc_data' + WRITE(*,*) ' ' + END IF +! + IF (ndata>=1) THEN + DEALLOCATE(ddata) + memory = memory - ndata*n_ddata + DEALLOCATE(idata) + memory = memory - ndata*n_idata + END IF + DEALLOCATE(sdata) + memory = memory - max(ndata,1)*nsmpl +! + RETURN + END SUBROUTINE dealloc_data diff --git a/forward/arrays.f90 b/forward/arrays.f90 new file mode 100644 index 0000000..7838fdf --- /dev/null +++ b/forward/arrays.f90 @@ -0,0 +1,738 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief declaration of all main variables, arrays and constants +!> @details +!> definition of global (dynamic) arrays, constants and main descriptions\n + MODULE arrays + IMPLICIT NONE + + !> @brief Numerical precision and min/max value. + !> @details + !> Numerical precision and min/max value. \n\n + !> (1) last digit precision \n + !> (2) min allowed dble value \n + !> (3) max allowed dble value \n + double precision, dimension (3) :: const_dble + + !> @brief Project suffix, filename extension. + !> @details + !> Project suffix, filename extension. \n\n + !> project name extension/suffix\n + !> Size: nsmpl. + character (len=80), allocatable, dimension (:) :: project_sfx + + ! Size of grid + ! ------------ + + !> @brief Cell dimension array, x-direction. + !> @details + !> Cell dimension array, x-direction. \n\n + !> delta size of cell, size i0. + double precision, allocatable, dimension (:) :: delx + + !> @brief Cell dimension array, y-direction. + !> @details + !> Cell dimension array, y-direction. \n\n + !> delta size of cell, size j0. + double precision, allocatable, dimension (:) :: dely + + !> @brief Cell dimension array, z-direction. + !> @details + !> Cell dimension array, z-direction. \n\n + !> delta size of cell, size k0. + double precision, allocatable, dimension (:) :: delz + + !> @brief Absolute cell center positions, x-direction. + !> @details + !> Absolute cell center positions, x-direction. \n\n + !> absolute position, size i0.\n\n + !> With reference to the left, front, bottom corner of the + !> model. + double precision, allocatable, dimension (:) :: delxa + + !> @brief Absolute cell center positions, y-direction. + !> @details + !> Absolute cell center positions, y-direction. \n\n + !> absolute position, size j0.\n\n + !> With reference to the left, front, bottom corner of the + !> model. + double precision, allocatable, dimension (:) :: delya + + !> @brief Absolute cell center positions, z-direction. + !> @details + !> Absolute cell center positions, z-direction. \n\n + !> absolute position, size k0.\n\n + !> With reference to the left, front, bottom corner of the + !> model. + double precision, allocatable, dimension (:) :: delza + + ! Variable arrays + ! --------------- + + !> @brief Variable array hydraulic potential. + !> @details + !> Variable array hydraulic potential. \n\n + !> Indices: \n + !> 1. i-index \n + !> 2. j-index \n + !> 3. k-index \n + !> 4. sample index \n + double precision, allocatable, dimension (:,:,:,:) :: head + + !> @brief Variable array pressure. + !> @details + !> Variable array pressure. \n\n + !> Indices: \n + !> 1. i-index \n + !> 2. j-index \n + !> 3. k-index \n + !> 4. sample index \n + double precision, allocatable, dimension (:,:,:,:) :: pres + + !> @brief Variable array temperature. + !> @details + !> Variable array temperature. \n\n + !> Indices: \n + !> 1. i-index \n + !> 2. j-index \n + !> 3. k-index \n + !> 4. sample index \n + double precision, allocatable, dimension (:,:,:,:) :: temp + + !> @brief Variable array concentrations. + !> @details + !> Variable array concentrations. \n\n + !> Indices: \n + !> 1. i-index \n + !> 2. j-index \n + !> 3. k-index \n + !> 4. species index \n + !> 5. sample index \n + double precision, allocatable, dimension (:,:,:,:,:) :: conc + + !> @brief Array of concentration iteration differences. + !> @details + !> Array of concentration iteration differences. \n\n + !> Used for checking concentration convergence. + double precision, allocatable, dimension (:,:) :: conc_conv + + !> @brief Array of total salinities. + !> @details + !> Array of total salinities. \n\n + !> Indices: \n + !> 1. i-index \n + !> 2. j-index \n + !> 3. k-index \n + !> 4. sample index \n + double precision, allocatable, dimension (:,:,:,:) :: tsal + + ! Variables for variable time stepping + ! ------------------------------------ + + !> @brief Array with flag for nonlinear iteration maxout. + !> @details + !> Array with flag for nonlinear iteration maxout. \n\n + !> + !> - "0": Initialized value \n + !> - "1": Nonlinear iteration fine, possibly double time + !> step. \n + !> - "-2": Iterative solver or Picard/Newton iteration reached + !> maxiter. Half time step. \n + !> + !> Variable for variable time stepping. + integer, allocatable, dimension (:) :: flag_delt + + !> @brief Array with counters for doubling time step. + !> @details + !> Array with counters for doubling time step. \n + !> + !> Variable for variable time stepping. + integer, allocatable, dimension (:) :: delt_count + + !> @brief Array containing information if it is the first timestep. + !> @details + !> Array containing information if it is the first timestep. \n + !> - 0: First time step \n + !> - 1: Not the first time step. \n\n + !> + !> The information is carried for each sample, the length will + !> be nsmpl. \n\n + !> + !> Variable for variable time stepping. + integer, allocatable :: flag_1st_timestep(:) + + !> @brief Array of previous time step lengths for variable time step. + !> @details + !> Array of previous time step lengths for variable time step. \n\n + !> + !> Variable for variable time stepping. + double precision, allocatable, dimension (:) :: delt_old + +! maximum of the used units/BC-units ("maxunits"/"bc_maxunits") + INTEGER nunits +! number of rock properties + boundary condition types, number of regular rock properties (to load) + INTEGER nprop, nprop_load +! first/last index of normal properties in 'nprop' + INTEGER maxunits, firstidx, lastidx +! first/last index of bc-units in 'nprop' + INTEGER bc_maxunits, bc_firstidx, bc_lastidx, nbc + +! string constants for the number of property-units and bc-units + character (len=2) :: c_npropunit, c_nbcunit, c_npv + + PARAMETER (firstidx=1) ! first rock properties + PARAMETER (lastidx=17) ! last rock properties + PARAMETER (bc_firstidx=18) ! first BC unit + PARAMETER (bc_lastidx=22) ! last BC unit + PARAMETER (nbc=bc_lastidx-bc_firstidx+1) + PARAMETER (nprop=lastidx-firstidx+1 +bc_lastidx-bc_firstidx+1) +! load fewer, except 3*bc-units + PARAMETER (nprop_load=nprop-nbc) + +! unit index number, unit-cell assignment (rock property for each cell) + INTEGER, ALLOCATABLE :: uindex(:,:,:) +! cell index number, no assignment - only for output (grouping) + INTEGER, ALLOCATABLE :: cindex(:,:,:) + +! def_props = '<name>' + DOUBLE PRECISION, ALLOCATABLE :: propunit(:,:,:) + +! disable additional hdf5-output + INTEGER nout_ijk + PARAMETER (nout_ijk=9) + LOGICAL out_ijk(nout_ijk) + INTEGER cout_i, cout_j, cout_k + PARAMETER (cout_i=1) + PARAMETER (cout_j=2) + PARAMETER (cout_k=3) + INTEGER cout_vx, cout_vy, cout_vz + PARAMETER (cout_vx=4) + PARAMETER (cout_vy=5) + PARAMETER (cout_vz=6) + INTEGER cout_rhof, cout_visf, cout_uindex + PARAMETER (cout_rhof=7) + PARAMETER (cout_visf=8) + PARAMETER (cout_uindex=9) + + INTEGER ncompress + PARAMETER (ncompress=4) + character (len=5) :: compress_suffix(ncompress) + DATA compress_suffix/'plain', 'bz2', 'gz', 'zip'/ + LOGICAL out_prop(nprop) + character (len=4) :: properties(nprop+2) + DATA properties/' por', 'a_kx', 'a_ky', ' kz', 'comp', & + 'a_lx', 'a_ly', ' lz', ' q', ' rc', ' df', ' ec', & + ' lc', ' bcl', 'bcpd', 's_nr', 's_wr', & + ' hbc', ' tbc', ' cbc', ' ebc', 'snbc', ' tp', ' sbc'/ + character (len=80) :: doc_properties(nprop+2) + DATA doc_properties/'porosity', & + 'permeability, anisotropic direction X (ratio of Z), default 1.0', & + 'permeability, anisotropic direction Y (ratio of Z), default 1.0', & + 'permeability, direction Z', & + 'compressibility of rock, default 1.0e-10', & + 'conductivity, anisotropic direction X (ratio of Z), default 1.0', & + 'conductivity, anisotropic direction Y (ratio of Z), default 1.0', & + 'conductivity, direction Z', & + 'heat production, default 0.0', & + 'heat capacity of rock, default 2.06e6', & + 'diffusivity, default 10.0', & + 'electrical conductivity, default 0.0', & + 'coupling coefficient, default 0.0', & + 'Brooks Corey "lambda" - pore size distribution index, default 2.0', & + 'Brooks Corey displacement pressure (PD), default 1.0d6', & + 'residual saturation of the non-wetting phase, default 0.05', & + 'residual saturation of the wetting phase, default 0.2', & + 'flow boundary condition', & + 'temperature boundary condition', & + 'concentration boundary condition', & + 'electric potential boundary condition', & + 'saturation (non-wetting) boundary condition', & + 'time periods', & + 'unspecified single cell boundary condition'/ + DOUBLE PRECISION prop_max(nprop_load) + DATA prop_max/1.0D0, 1.0D+30, 1.0D+30, 1.0D+30, 1.0D+50, & + 1.0D+30, 1.0D+30, 1.0D+30, 1.0D+30, 1.0D+30, 1.0D+30, 1.0D+30, & + 1.0D+50, 10.0d0, 1.0D+30, 1.0D0, 1.0D0/ + DOUBLE PRECISION prop_min(nprop_load) + DATA prop_min/1.0D-30, 1.0D-3, 1.0D-3, 1.0D-30, 1.0D-50, & + 1.0D-3, 1.0D-3, 1.0D-3, 1.0D-20, 1.0D-10, 0.0D0, 1.0D-10, & + 1.0D-50, 1.0D-2, 0.0D0, 0.0D0, 0.0D0/ + DOUBLE PRECISION prop_default(nprop_load) + DATA prop_default/1.0D-7, 1.0D0, 1.0D0, 1.0D-20, 1.0D-10, & + 1.0D0, 1.0D0, 2.0D0, 0.0D0, 2.0D6, 10.0D0, 0.0D0, & + 0.0D0, 2.0D0, 1.0D3, 0.05D0, 0.2D0/ + +! ------------------------------------------ + INTEGER idx_por + INTEGER idx_an_kx + INTEGER idx_an_ky + INTEGER idx_kz + INTEGER idx_comp + INTEGER idx_an_lx + INTEGER idx_an_ly + INTEGER idx_lz + INTEGER idx_q + INTEGER idx_rc + INTEGER idx_df + INTEGER idx_ec + INTEGER idx_lc + + + INTEGER idx_s_nr + INTEGER idx_s_wr + INTEGER idx_hbc + INTEGER idx_tbc + INTEGER idx_cbc + INTEGER idx_ebc + INTEGER idx_snbc +! integer idx_pbc + + PARAMETER (idx_por=1) + PARAMETER (idx_an_kx=2) + PARAMETER (idx_an_ky=3) + PARAMETER (idx_kz=4) + PARAMETER (idx_comp=5) + PARAMETER (idx_an_lx=6) + PARAMETER (idx_an_ly=7) + PARAMETER (idx_lz=8) + PARAMETER (idx_q=9) + PARAMETER (idx_rc=10) + PARAMETER (idx_df=11) + PARAMETER (idx_ec=12) + PARAMETER (idx_lc=13) + + + PARAMETER (idx_s_nr=16) + PARAMETER (idx_s_wr=17) + PARAMETER (idx_hbc=18) + PARAMETER (idx_tbc=19) + PARAMETER (idx_cbc=20) + PARAMETER (idx_ebc=21) + PARAMETER (idx_snbc=22) +! parameter (idx_pbc = 18)?? like idx_hbc +! ------------------------------------------ + INTEGER idx_tp + INTEGER idx_sbc + PARAMETER (idx_tp=nprop+1) + PARAMETER (idx_sbc=nprop+2) +! ------------------------------------------ + +! new boundary-condition structures +! i,j,k - position + INTEGER cbc_i, cbc_j, cbc_k + PARAMETER (cbc_i=1) + PARAMETER (cbc_j=2) + PARAMETER (cbc_k=3) +! bc-unit, bc time dependend + INTEGER cbc_bcu, cbc_bctp + PARAMETER (cbc_bcu=4) + PARAMETER (cbc_bctp=5) +! physical value, boundary type (neuman, dirichlet), sub index (species) + INTEGER cbc_pv, cbc_bt, cbc_si, cbc_dir + PARAMETER (cbc_pv=6) + PARAMETER (cbc_bt=7) + PARAMETER (cbc_si=8) + PARAMETER (cbc_dir=9) +! bc-type max index + INTEGER nibc, ndbc + PARAMETER (nibc=9) +! 1:value, 2:bcmy, 3:additional value (e.g. for well function pressure) + PARAMETER (ndbc=3) + + ! Physical value (pv) indices and names + ! ------------------------------------- + + !> @brief Physical value index: head. + !> @details + !> Physical value index: head. \n\n + integer, parameter :: pv_head = 1 + + !> @brief Physical value index: temp. + !> @details + !> Physical value index: temp. \n\n + integer, parameter :: pv_temp = 2 + + !> @brief Physical value index: conc. + !> @details + !> Physical value index: conc. \n\n + integer, parameter :: pv_conc = 3 + + !> @brief Physical value index: pres. + !> @details + !> Physical value index: pres. \n\n + integer, parameter :: pv_pres = 5 + + !> @brief Physical value index: bhpr. + !> @details + !> Physical value index: bhpr. \n\n + !> Special case for borehole output. + integer, parameter :: pv_bhpr = 6 + + !> @brief Number of physical value indices. + !> @details + !> Number of physical value indices. \n\n + !> Or: pv max index. + integer, parameter :: npv = 6 + + !> @brief Array of physical value names. + !> @details + !> Array of physical value names. \n\n + character (len=4), parameter, dimension (npv) :: pv_name = & + (/'head', 'temp', 'conc', 'nova', 'pres', 'bhpr'/) + + !> @brief Array of physical value output switches. + !> @details + !> Array of physical output switches. \n\n + !> Switches are set according to activity of variables. Output + !> (vtk/hdf5) for specific variables can be suppressed by + !> specifying the physical value name in `# disable output`. + logical out_pv(npv) + +! bc-type + INTEGER bt_diri, bt_neum, bt_neuw + PARAMETER (bt_diri=1) + PARAMETER (bt_neum=2) + PARAMETER (bt_neuw=3) + character (len=3) :: bc_name(3) + DATA bc_name/'bcd', 'bcn', 'bcw'/ +! boundary-condition structures + INTEGER, ALLOCATABLE :: ibc_data(:,:) + DOUBLE PRECISION, ALLOCATABLE :: dbc_data(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: dbc_dataold(:) + +! borehole logs + INTEGER nbh_logs + INTEGER, ALLOCATABLE :: ibh_pos(:,:) + character (len=256), dimension (:), allocatable :: cbh_name + +! Begin and End of the pv-blocks after sorting +! reuse *_flow for head and pres !!! + INTEGER first_flow, last_flow + INTEGER first_temp, last_temp + INTEGER first_conc, last_conc + INTEGER nbc_data + + ! Observed data + ! ------------- + + !> @brief Array of integer data specifications. + !> @details + !> Array of integer data specifications. \n + !> Index 2: [i,j,k, type, sub-index, obs] + integer, allocatable, dimension (:,:) :: idata + + !> @brief Array of double precision data specifications. + !> @details + !> Array of double precision data specifications. \n + !> Index2: [value, weighting, time, px,py,pz] + double precision, allocatable, dimension (:,:) :: ddata + + !> @brief Array of simulated data values. + !> @details + !> Array of simulated data values. \n + !> Save the computed values to compare it with + !> 'ddata(:,cid_pv)' \n + !> Index 2: Sample index. + double precision, allocatable, dimension (:,:) :: sdata + + !> @brief Index position in idata for i. + !> @details + !> Index position in idata for i. \n + integer, parameter :: cid_i = 1 + + !> @brief Index position in idata for j. + !> @details + !> Index position in idata for j. \n + integer, parameter :: cid_j = 2 + + !> @brief Index position in idata for k. + !> @details + !> Index position in idata for k. \n + integer, parameter :: cid_k = 3 + + !> @brief Index position in idata for type. + !> @details + !> Index position in idata for type. \n + integer, parameter :: cid_pv = 4 + + !> @brief Index position in idata for sub-index. + !> @details + !> Index position in idata for sub-index. \n + integer, parameter :: cid_si = 5 + + !> @brief Index position in idata for obs. + !> @details + !> Index position in idata for obs. \n + integer, parameter :: cid_obs = 6 + + !> @brief Index-2 dimension of idata. + !> @details + !> Index-2 dimension of idata. \n + !> Number of different integer-parameters arrays in idata. + integer, parameter :: n_idata = 6 + + !> @brief Index position in ddata for value. + !> @details + !> Index position in ddata for value. \n + integer, parameter :: cdd_pv = 1 + + !> @brief Index position in ddata for weighting. + !> @details + !> Index position in ddata for weighting. \n + integer, parameter :: cdd_w = 2 + + !> @brief Index position in ddata for time. + !> @details + !> Index position in ddata for time. \n + integer, parameter :: cdd_time = 3 + + !> @brief Index position in ddata for px. + !> @details + !> Index position in ddata for px. \n + integer, parameter :: cdd_i = 4 + + !> @brief Index position in ddata for py. + !> @details + !> Index position in ddata for py. \n + integer, parameter :: cdd_j = 5 + + !> @brief Index position in ddata for pz. + !> @details + !> Index position in ddata for pz. \n + integer, parameter :: cdd_k = 6 + + !> @brief Index-2 dimension of ddata. + !> @details + !> Index-2 dimension of ddata. \n + !> Number of different double-precision-parameters arrays in + !> ddata. + integer, parameter :: n_ddata = 6 + +! jump table between parameter index and seeding + INTEGER, ALLOCATABLE :: seed_para(:,:) + INTEGER, ALLOCATABLE :: gpara(:) + + ! Coefficients for linear system solver + ! ------------------------------------- + + !> @brief Linear system solver coefficent array a. + !> @details + !> Linear system solver coefficent array a. \n + DOUBLE PRECISION, ALLOCATABLE :: a(:,:,:,:) + + !> @brief Linear system solver coefficent array b. + !> @details + !> Linear system solver coefficent array b. \n + DOUBLE PRECISION, ALLOCATABLE :: b(:,:,:,:) + + !> @brief Linear system solver coefficent array c. + !> @details + !> Linear system solver coefficent array c. \n + DOUBLE PRECISION, ALLOCATABLE :: c(:,:,:,:) + + !> @brief Linear system solver coefficent array d. + !> @details + !> Linear system solver coefficent array d. \n + DOUBLE PRECISION, ALLOCATABLE :: d(:,:,:,:) + + !> @brief Linear system solver coefficent array e. + !> @details + !> Linear system solver coefficent array e. \n + DOUBLE PRECISION, ALLOCATABLE :: e(:,:,:,:) + + !> @brief Linear system solver coefficent array f. + !> @details + !> Linear system solver coefficent array f. \n + DOUBLE PRECISION, ALLOCATABLE :: f(:,:,:,:) + + !> @brief Linear system solver coefficent array g. + !> @details + !> Linear system solver coefficent array g. \n + DOUBLE PRECISION, ALLOCATABLE :: g(:,:,:,:) + + !> @brief Linear system solver coefficent array w. + !> @details + !> Linear system solver coefficent array w. \n + DOUBLE PRECISION, ALLOCATABLE :: w(:,:,:,:) + + !> @brief Linear system solver coefficent array x. + !> @details + !> Linear system solver coefficent array x. \n + DOUBLE PRECISION, ALLOCATABLE :: x(:,:,:,:) + +! [r0] random number vector, used for BiCGStab algorithm + DOUBLE PRECISION, ALLOCATABLE :: r(:,:,:) +! openmp-private/locale vectors for linear system solver (lss_*) +! team-global buffer for boundary exchange (+ismpl) + DOUBLE PRECISION, ALLOCATABLE :: lss_bound_block(:,:,:,:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_dnrm(:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_tmp(:,:) +! private copy for preconditioning (+Tlevel_1 +ismpl) + DOUBLE PRECISION, ALLOCATABLE :: lss_lma(:,:,:), lss_lmb(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lmc(:,:,:), lss_lmd(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lme(:,:,:), lss_lmf(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lmg(:,:,:), lss_lud(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lx(:,:,:), lss_lb(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lloctmp(:,:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_ldnrm(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_ud_block(:,:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: lss_lr0_hat(:,:,:) + +! for ilu-precond. (shadow vectors) + DOUBLE PRECISION, ALLOCATABLE :: ud(:,:,:,:) +! marker of current boundary conditions elements + CHARACTER, ALLOCATABLE :: bc_mask(:,:) + +! boundary condition info, values 'n','d',' ' on positions [head,temp,conc,pres] + character (len=npv), dimension (:,:,:), allocatable :: node_info + +! spez. ILU arrays +! proc. index of block + INTEGER, ALLOCATABLE :: proza(:,:,:) + + !> @brief Array for storing old head for iteration. + !> @details + !> Array for storing old head for iteration. \n\n + !> Indices: \n + !> 1. linear cell-index \n + !> 2. cgen-level index \n + !> 3. sample index\n + !> Size: [I0*J0*K0,ncgen,nsmpl], used for forward newton iteration + double precision, allocatable, dimension (:,:,:) :: headold + + !> @brief Array for storing old temp for iteration. + !> @details + !> Array for storing old temp for iteration. \n\n + !> Indices: \n + !> 1. linear cell-index \n + !> 2. cgen-level index \n + !> 3. sample index\n + !> Size: [I0*J0*K0,ncgen,nsmpl], used for forward newton iteration + double precision, allocatable, dimension (:,:,:) :: tempold + + !> @brief Array for storing old pressure for iteration. + !> @details + !> Array for storing old pressure for iteration. \n\n + !> Indices: \n + !> 1. linear cell-index \n + !> 2. cgen-level index \n + !> 3. sample index\n + !> Size: [I0*J0*K0,ncgen,nsmpl], used for forward newton iteration + double precision, allocatable, dimension (:,:,:) :: presold + + !> @brief Array for storing old conc for iteration. + !> @details + !> Array for storing old conc for iteration. \n\n + !> Indices: \n + !> 1. linear cell-index \n + !> 2. species index \n + !> 3. cgen-level index \n + !> 4. sample index\n + !> Size: [I0*J0*K0,max(ntrans,1),ncgen,nsmpl], used for forward newton iteration + double precision, allocatable, dimension (:,:,:,:) :: concold + +! BC time period: (period-index,value-type,TP-ID,sample) +! - value-type: time, BC-value + DOUBLE PRECISION, ALLOCATABLE :: bcperiod(:,:,:,:) +! BC time period - number of periods: (TP-ID) + INTEGER, ALLOCATABLE :: ibcperiod(:) +! BC time period - on/off-switch: (period-index,TP-ID) + LOGICAL, ALLOCATABLE :: lbcperiod(:,:) + + !> @brief Array of output times. + !> @details + !> Array of output times. \n + !> Define output times (time dependend) \n + !> Read under `# output times`. \n + double precision, allocatable, dimension (:) :: outt + +! define monitor index, used for "simulate" + INTEGER, ALLOCATABLE :: smon_idx(:) + + !> @brief Array of time step durations/lengths/values. + !> @details + !> Array of time step durations/lengths/values. \n + !> The time step lengths are computed in `calc_deltatime` + !> according to the input under `# time periods`: \n + !> - start and end times of the time periods \n + !> - number of time steps per period \n + !> - step type (f.e. distributed linearly, logarithmically) \n + double precision, allocatable, dimension (:) :: delta_time + + !> @brief Simulation time + !> @details + !> Simulation time. \n + !> Simulation time for each sample are set in + !> `forward/forward_iter.f90`. + double precision, allocatable, dimension (:) :: simtime + + !> @brief Samples array for transient switches + !> @details + !> Samples array for transient switches. \n\n + !> + !> transient execption, to toggle it off + logical, allocatable, dimension (:) :: tr_switch + + INTEGER c_fhandler, c_foffset +! [max # of files per thread] + PARAMETER (c_fhandler=100) +! file-handler offset + PARAMETER (c_foffset=30) +! file handler table + INTEGER, ALLOCATABLE :: fh_table(:,:) + +! - convergency history buffer - +! max history length + INTEGER conv_hlen + PARAMETER (conv_hlen=50) +! number of histories + INTEGER conv_hmax +! history buffer + DOUBLE PRECISION, ALLOCATABLE :: conv_history(:,:,:) +! current history length + INTEGER, ALLOCATABLE :: conv_chlen(:,:) +! current position index + INTEGER, ALLOCATABLE :: conv_ipos(:,:) +! convergency, when this vector is true + LOGICAL, ALLOCATABLE :: lcon(:,:) + +! default flow values from read_model.f90 + DOUBLE PRECISION, ALLOCATABLE :: vdefault(:,:) + LOGICAL :: vdefaultswitch + +! transport + DOUBLE PRECISION, ALLOCATABLE :: mmas_c(:) + DOUBLE PRECISION, ALLOCATABLE :: diff_c(:) + DOUBLE PRECISION, ALLOCATABLE :: beta_c(:) + + +! OpenMP REDUCTION arrays + DOUBLE PRECISION, ALLOCATABLE :: omp_dglobal(:,:,:) + INTEGER, ALLOCATABLE :: omp_iglobal(:,:,:) + +!---- only for DEBUG !!! ---- + INTEGER n_debugout +! [2,n_debugout]: 1: time step, 2: nl iteration + INTEGER, ALLOCATABLE :: debugout(:,:) + + END MODULE arrays diff --git a/forward/bhpr.f90 b/forward/bhpr.f90 new file mode 100644 index 0000000..dd5a7e1 --- /dev/null +++ b/forward/bhpr.f90 @@ -0,0 +1,149 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate well pressure according to Shu,2005 +!> @param[in] ismpl local sample index +!> @param[in] ii i cell-index +!> @param[in] jj i cell-index +!> @param[in] kk i cell-index +!> @details +!> Reference: J. Shu\n COMPARISON OF VARIOUS TECHINQUES FOR COMPUTING +!> WELL INDEX\n Master Thesis, Stanford 2005\n\n +!> +!> modify coefficents for the head equation according to the boundary +!> conditions, coefficients are stored as vectors in the diagonals a-g +!> (d center), and rhs in w.\n + DOUBLE PRECISION FUNCTION bhpr(ii,jj,kk,ismpl) + + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_flow + use mod_time + use mod_linfos + + IMPLICIT NONE + + integer :: ismpl + integer :: i, j, k + integer :: ib +! + INTEGER ii, jj, kk, bcu, tpbcu, bctype, i_dir + DOUBLE PRECISION val, malfa, mbeta + DOUBLE PRECISION d_x,d_y,d_z,k_x,k_y,k_z,wi_x,wi_y,wi_z,wi_pj + ! DOUBLE PRECISION l_x,l_y + DOUBLE PRECISION l_z + DOUBLE PRECISION r_b,r_w,skin + ! DOUBLE PRECISION xz,zx,yz,zy + DOUBLE PRECISION xy,yx + DOUBLE PRECISION kx,ky,kz,visf +! + PARAMETER (skin=0.d0,r_w=0.15) +! + EXTERNAL kx,ky,kz,visf + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - +! neumann nodes - - - - - - - - - - - - - - - - - - - - - - - - - - +! + ! default well pressure + bhpr = 0.0d0 + + DO ib = first_flow, last_flow + + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bctype = ibc_data(ib,cbc_bt) + + ! neumann bc?, skip otherwise + ! data point? skip otherwise + IF (ii==i.AND.jj==j .AND. kk==k .AND. bctype==bt_neuw) THEN + + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + i_dir = ibc_data(ib,cbc_dir) + + ! WELLMODEL + ! discrete values + val = dbc_data(ib,1,ismpl) + + IF ((tpbcu>0) .AND. nbctp>0) THEN + + ! time-dependent bc: val=ac*val+bc + ! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) + + ! update time dependend modification of the bc-value + val = malfa + mbeta*val + + END IF +! + IF (tpbcu>=0) THEN + + k_x = kx(i,j,k,ismpl) + k_y = ky(i,j,k,ismpl) + k_z = kz(i,j,k,ismpl) + + d_x = delx(i) + d_y = dely(j) + d_z = delz(k) + +! l_x=0.d0 +! yz=k_y/k_z +! zy=k_z/k_y +! r_b=0.28d0*sqrt((sqrt(yz)*d_z**2+sqrt(zy)*d_y**2))/ & +! (yz**0.25+zy**0.25) +! wi_x = 2.0d0*pi*sqrt(k_y*k_z)*l_x/(log(r_b/r_w)+skin) + wi_x = 0.0d0 + +! l_y=0.d0 +! xz=k_x/k_z +! zx=k_z/k_x +! r_b=0.28d0*sqrt((sqrt(xz)*d_z**2+sqrt(zx)*d_x**2))/ & +! (xz**0.25+zx**0.25) +! wi_y = 2.0d0*pi*sqrt(k_x*k_z)*l_y/(log(r_b/r_w)+skin) + wi_y = 0.0d0 + + l_z = d_z + xy = k_x/k_y + yx = k_y/k_x + r_b = 0.28d0*sqrt((sqrt(xy)*d_y**2+sqrt(yx)*d_x**2))/ & + (xy**0.25+yx**0.25) + wi_z = 2.0d0*pi*sqrt(k_x*k_y)*l_z/(log(r_b/r_w)+skin) + + wi_pj = sqrt(wi_x**2 + wi_y**2 + wi_z**2) + + bhpr = pres(i,j,k,ismpl)+val*visf(i,j,k,ismpl)/wi_pj + + dbc_data(ib,3,ismpl) = bhpr + + END IF + END IF +! + END DO +! + RETURN + END diff --git a/forward/check_change.f90 b/forward/check_change.f90 new file mode 100644 index 0000000..9622e78 --- /dev/null +++ b/forward/check_change.f90 @@ -0,0 +1,134 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check changes between vectors [new] and [old] +!> @param[in] mode switch absolute/relative +!> @param[out] rms return value +!> @param[out] difmax maximal difference +!> @param[in] ni I-dimension for vectors [new], [old] +!> @param[in] nj J-dimension for vectors [new], [old] +!> @param[in] nk K-dimension for vectors [new], [old] +!> @param[in] new vector with new values +!> @param[in] old vector with old values +!> @param[in] pv_idx index number (physical value), only needed for AD code generation/modification +!> @param[out] loc_nltol tolerance criteria, only needed for AD code generation/modification +!> @param[in] ismpl local sample index +!> @details +!> Computes two difference metrics between the physical variable array +!> of this iteration (new) and the one from the previous iteration +!> (old): \n\n +!> +!> 1. difmax : max. difference of fields new and old\n +!> mode= 0 : difmax is absolute maximum difference\n +!> else : difmax is relative maximum difference\n\n +!> +!> 2. rms : root mean square difference of fields new and old +!> mode= 0 : rms is root mean square of absolute differences\n +!> else : rms is root mean square of relative differences\n\n + SUBROUTINE check_change(mode,pv_idx,loc_nltol,rms,difmax,ni,nj,nk,new,old,ismpl) + + use arrays + use mod_linfos + + IMPLICIT NONE + + INTEGER i, j, k, ni, nj, nk, ijk, ipt, jpt, kpt, mode, pv_idx, ismpl + DOUBLE PRECISION new(ni,nj,nk), old(ni,nj,nk) + ! DOUBLE PRECISION dif + DOUBLE PRECISION rms, difmax, loc_nltol + INTEGER idamax + EXTERNAL idamax + INTRINSIC dabs, dble, sqrt + + + IF (linfos(3)>=2) WRITE(*,*) ' ... check_change' + + ! Initial values for output + rms = 0.D0 + difmax = 0.D0 + ipt = 0 + jpt = 0 + kpt = 0 + + IF (mode==0) THEN + ! Absolute difference + + ! Number of cells + ijk = ni*nj*nk + + ! Copy new values to x + CALL dcopy(ijk,new,1,x(1,1,1,ismpl),1) + + ! Absolute difference array: new - old + CALL daxpy(ijk,-1.0d0,old,1,x(1,1,1,ismpl),1) + + ! Indices of maximum absolute difference + i = idamax(ijk,x(1,1,1,ismpl),1) + CALL ijk_m(i,ipt,jpt,kpt) + + ! Maximum absolute difference + difmax = x(ipt,jpt,kpt,ismpl) + + ! Sum of squares + CALL s_ddot(ijk,x(1,1,1,ismpl),x(1,1,1,ismpl),rms) + + ELSE + ! Relative difference (currently not used) + + ! Number of cells + ijk = ni*nj*nk + + ! Copy new values to x + CALL dcopy(ijk,new,1,x(1,1,1,ismpl),1) + + ! Relative difference array (new - old)/old + CALL daxpy(ijk,-1.0d0,old,1,x(1,1,1,ismpl),1) + DO k = 1, nk + DO j = 1, nj + DO i = 1, ni + IF (dabs(old(i,j,k))>1.D-200) x(i,j,k,ismpl) = x(i,j,k,ismpl)/old(i,j,k) + END DO + END DO + END DO + + ! Indices of maximum relative difference + i = idamax(ijk,x(1,1,1,ismpl),1) + CALL ijk_m(i,ipt,jpt,kpt) + + ! Maximum relative difference + difmax = x(ipt,jpt,kpt,ismpl) + + ! Sum of squares + CALL s_ddot(ijk,x(1,1,1,ismpl),x(1,1,1,ismpl),rms) + + END IF + + ! Root-Mean part of the RMSE + rms = sqrt(rms/dble(ijk)) + + ! Standard output + IF (linfos(3)>=2) WRITE(*,'(A,1e12.5,A,1e12.5,3(A,i5),A)') & + ' nl iteration rms =', rms, ', difmax =', difmax, ', [', & + ipt, ',', jpt, ',', kpt, ']' + + RETURN + END diff --git a/forward/check_props.f90 b/forward/check_props.f90 new file mode 100644 index 0000000..b31c005 --- /dev/null +++ b/forward/check_props.f90 @@ -0,0 +1,76 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute reference value of "rhof" +!> @param[in] ismpl local sample index +!> @details +!> recompute the reference value [rref] and\n +!> makes a sanity proof with the given (default) one\n + SUBROUTINE check_props(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION rmin, rmax, ravrg, rlocal, rhof + EXTERNAL rhof + +#ifdef head_base +! check rref + rmin = rhof(1,1,1,ismpl) + rmax = rhof(1,1,1,ismpl) + ravrg = 0.D0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + rlocal = rhof(i,j,k,ismpl) + ravrg = ravrg + rlocal + rmin = min(rlocal,rmin) + rmax = max(rlocal,rmax) + END DO + END DO + END DO + ravrg = ravrg/dble(i0*j0*k0) +! + IF (rref>rmax) THEN + WRITE(*,'(1A,1e12.4,1A)') 'error: rref=', rref, & + ' not consistent' + WRITE(*,'(3A,4(1e12.4,1A))') & + 'You should explicitely define a ',& + 'section "'//key_char//' rref" with ', & + 'a value like ', rmax, & + ', calulated range [', rmin, ', ', ravrg, ', ', rmax, & + '] !!!' + rref=rmax +!vr rref=ravrg + WRITE(*,'(1A,1e12.4,1A)') 'rref set to:', rref, & + ' (= rmax)' + END IF +! +#endif + + RETURN + END diff --git a/forward/check_units.f90 b/forward/check_units.f90 new file mode 100644 index 0000000..bc0624a --- /dev/null +++ b/forward/check_units.f90 @@ -0,0 +1,161 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief prove the thickness for each unit layer +!> @param[in] ismpl local sample index +!> @details +!> count for each rock layer the number of cell neighbours\n +!> and warns about small layers (currently disabled !!!)\n + SUBROUTINE check_units(ismpl) + use arrays + use mod_genrl + IMPLICIT NONE +! counts the directions (thickness large enough) + INTEGER icount +! current unit, min. thickness criteria, () + INTEGER un, xdcrit, lines +! delta offset for neighbours + INTEGER d_i, d_j, d_k +! interval 'i':[iv,ib] + INTEGER iv_, ib_, id_ +! interval 'j':[jv_,jb_] + INTEGER jv_, jb_, jd_ +! interval 'k':[kv_,kb_] + INTEGER kv_, kb_, kd_ +! counts all to small areas for each unit + INTEGER, ALLOCATABLE :: warn(:,:) +! : in percentage + DOUBLE PRECISION warn_p + integer :: i + integer :: j + integer :: k + integer :: ismpl + +! --- routine disabled !!! --- + RETURN +! --- routine disabled !!! --- + +! init. + lines = 0 + ALLOCATE(warn(maxunits,2)) + DO i = 1, maxunits + warn(i,1) = 0 + warn(i,2) = 0 + END DO + +! setup all ranges + iv_ = 3 + ib_ = i0 - 2 + id_ = 1 + IF (i0<5) THEN +! disable this dimension + iv_ = 1 + ib_ = i0 + id_ = 0 + END IF + jv_ = 3 + jb_ = j0 - 2 + jd_ = 1 + IF (j0<5) THEN +! disable this dimension + jv_ = 1 + jb_ = j0 + jd_ = 0 + END IF + kv_ = 3 + kb_ = k0 - 2 + kd_ = 1 + IF (k0<5) THEN +! disable this dimension + kv_ = 1 + kb_ = k0 + kd_ = 0 + END IF + +! setup right criteria + IF (id_+jd_+kd_==1) THEN +! 1D criteria + xdcrit = 1 + ELSE IF (id_+jd_+kd_==2) THEN +! 2D criteria + xdcrit = 3 + ELSE +! 3D criteria + xdcrit = 7 + END IF + +! analyse all inner elements + DO k = kv_, kb_ + DO j = jv_, jb_ + DO i = iv_, ib_ +! current unit number + un = uindex(i,j,k) + icount = 0 +! prove for all directions + DO d_k = -kd_, + kd_ + DO d_j = -jd_, + jd_ + DO d_i = -id_, + id_ + IF ((d_i/=0) .OR. (d_j/=0) .OR. (d_k/=0)) THEN + IF (((uindex(i+d_i,j+d_j,k+d_k)== & + un) .AND. (uindex(i-d_i,j-d_j,k-d_k)== & + un)) .OR. ((uindex(i+d_i,j+d_j,k+d_k)== & + un) .AND. (uindex(i+2*d_i,j+2*d_j,k+2*d_k)== & + un)) .OR. ((uindex(i-d_i,j-d_j,k-d_k)== & + un) .AND. (uindex(i-2*d_i,j-2*d_j,k-2*d_k)== & + un))) icount = icount + 1 + END IF + END DO + END DO + END DO + + IF ((icount/2)<xdcrit) THEN +! thickness to small !!! + warn(un,1) = warn(un,1) + 1 + ELSE +! enough thickness !!! + warn(un,2) = warn(un,2) + 1 + END IF + END DO + END DO + END DO + +! make an output for all units layers which are to small + DO i = 1, maxunits + IF (warn(i,1)+warn(i,2)>27) THEN + warn_p = dble(warn(i,1))/dble(warn(i,1)+warn(i,2)) + IF (warn_p>0.01D0) THEN + IF (lines==0) THEN + WRITE(*,*) + lines = 1 + END IF + WRITE(*,'(A,I7,A,F5.1,A)') ' *** warning: unit layer ' & + , i, ' is too fine (about ', warn_p*100.0D0, '%) ***' + END IF + END IF + END DO + IF (lines==1) WRITE(*,*) + +! free memory + DEALLOCATE(warn) + + RETURN + END diff --git a/forward/conc/calc_conc.f90 b/forward/conc/calc_conc.f90 new file mode 100644 index 0000000..a6790b9 --- /dev/null +++ b/forward/conc/calc_conc.f90 @@ -0,0 +1,107 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief top level routine for setup and computing tracer concentration +!> @param[in] species tracer species index +!> @param[in] ismpl local sample index + SUBROUTINE calc_conc(species,ismpl) + use arrays +! use chem_arrays + use mod_genrlc + use mod_genrl + use mod_conc + use mod_time + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i + INCLUDE 'OMP_TOOLS.inc' + INTEGER ijk, species + + + IF (linfos(3)>=2) WRITE(*,'(1A,i4)') ' ... calc_conc', & + species +! +! selecting a part for each thread +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + + ijk = i0*j0*k0 +! default to mark a non-boundary +!$OMP master + DO i = 1, ijk + bc_mask(i,ismpl) = '+' + END DO +!$OMP end master +! initialize coefficients for sparse solvers + CALL omp_set_dval(ijk,0.D0,a(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,b(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,c(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,d(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,e(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,f(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,g(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,w(1,1,1,ismpl)) + +!$OMP barrier +! calculate coefficients + CALL set_ccoef(species,ismpl) +! set energy sources/sinks + CALL set_cq(species,ismpl) + +!$OMP barrier + CALL set_ccoefrs(species,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + +! set boundary conditions + CALL set_cbc(species,ismpl) + + IF (linfos(3)>=2) WRITE(*,'(A,i4)') ' calling solve (conc)', & + species + +! write(99,'(a)') 'AC' +! write(99,'(10G15.6)') (a(3,3,k,1),k=1,k0) +! write(99,'(a)') 'BC' +! write(99,'(10G15.6)') (b(3,3,k,1),k=1,k0) +! write(99,'(a)') 'CC' +! write(99,'(10G15.6)') (c(3,3,k,1),k=1,k0) +! write(99,'(a)') 'DC' +! write(99,'(10G15.6)') (d(3,3,k,1),k=1,k0) +! write(99,'(a)') 'EC' +! write(99,'(10G15.6)') (e(3,3,k,1),k=1,k0) +! write(99,'(a)') 'FC' +! write(99,'(10G15.6)') (f(3,3,k,1),k=1,k0) +! write(99,'(a)') 'GC' +! write(99,'(10G15.6)') (g(3,3,k,1),k=1,k0) +! write(99,'(a)') 'WC' +! write(99,'(10G15.6)') (w(3,3,k,1),k=1,k0) +! solve it + CALL solve(pv_conc,species,conc(1,1,1,species,ismpl),errc, & + aparc,controlc,ismpl) + + RETURN + END diff --git a/forward/conc/cfluxes.f90 b/forward/conc/cfluxes.f90 new file mode 100644 index 0000000..e5375b3 --- /dev/null +++ b/forward/conc/cfluxes.f90 @@ -0,0 +1,338 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate x mass flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return x mass flux + DOUBLE PRECISION FUNCTION sx(i,j,k,l,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + DOUBLE PRECISION dif, di + EXTERNAL di + + sx = 0.D0 + IF (i0>1 .AND. i<i0) THEN + dif = conc(i+1,j,k,l,ismpl) - conc(i,j,k,l,ismpl) + sx = -di(i,j,k,l,ismpl)*dif + END IF + + RETURN + END + +!> @brief calculate y mass flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return y mass flux + DOUBLE PRECISION FUNCTION sy(i,j,k,l,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + DOUBLE PRECISION dif, dj + EXTERNAL dj + + sy = 0.D0 + IF (j0>1 .AND. j<j0) THEN + dif = conc(i,j+1,k,l,ismpl) - conc(i,j,k,l,ismpl) + sy = -dj(i,j,k,l,ismpl)*dif + END IF + + RETURN + END + +!> @brief calculate z mass flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return z mass flux + DOUBLE PRECISION FUNCTION sz(i,j,k,l,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + DOUBLE PRECISION dif, dk + EXTERNAL dk + + sz = 0.D0 + IF (k0>1 .AND. k<k0) THEN + dif = conc(i,j,k+1,l,ismpl) - conc(i,j,k,l,ismpl) + sz = -dk(i,j,k,l,ismpl)*dif + END IF + + RETURN + END + +!> @brief calculate x mass flux at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return x mass flux + DOUBLE PRECISION FUNCTION sxc(i,j,k,l,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + DOUBLE PRECISION d1, d2, di, amean + EXTERNAL di, amean + + sxc = 0.D0 + IF (i0<=1) RETURN + IF (i>1 .AND. i<i0) THEN + d1 = conc(i+1,j,k,l,ismpl) - conc(i,j,k,l,ismpl) + d2 = conc(i,j,k,l,ismpl) - conc(i-1,j,k,l,ismpl) + sxc = amean(-di(i,j,k,l,ismpl)*d1,-di(i-1,j,k,l,ismpl)*d2) + ELSE IF (i==1) THEN + sxc = -di(i,j,k,l,ismpl)*(conc(i+1,j,k,l,ismpl)-conc(i,j,k,l & + ,ismpl)) + ELSE IF (i==i0) THEN + sxc = -di(i-1,j,k,l,ismpl)*(conc(i,j,k,l,ismpl)-conc(i-1,j,k & + ,l,ismpl)) + END IF + + RETURN + END + +!> @brief calculate y mass fluxat cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return y mass flux + DOUBLE PRECISION FUNCTION syc(i,j,k,l,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + DOUBLE PRECISION d1, d2, dj, amean + EXTERNAL dj, amean + + syc = 0.D0 + IF (j0<=1) RETURN + IF (j>1 .AND. j<j0) THEN + d1 = conc(i,j+1,k,l,ismpl) - conc(i,j,k,l,ismpl) + d2 = conc(i,j,k,l,ismpl) - conc(i,j-1,k,l,ismpl) + syc = amean(-dj(i,j,k,l,ismpl)*d1,-dj(i,j-1,k,l,ismpl)*d2) + ELSE IF (j==1) THEN + syc = -dj(i,j,k,l,ismpl)*(conc(i,j+1,k,l,ismpl)-conc(i,j,k,l & + ,ismpl)) + ELSE IF (j==j0) THEN + syc = -dj(i,j-1,k,l,ismpl)*(conc(i,j,k,l,ismpl)-conc(i,j-1,k & + ,l,ismpl)) + END IF + + RETURN + END + +!> @brief calculate z mass flux at cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] l species +!> @param[in] ismpl local sample index +!> @return z mass flux + DOUBLE PRECISION FUNCTION szc(i,j,k,l,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + DOUBLE PRECISION d1, d2, dk, amean + EXTERNAL dk, amean + + szc = 0.D0 + IF (k0<=1) RETURN + IF (k>1 .AND. k<k0) THEN + d1 = conc(i,j,k+1,l,ismpl) - conc(i,j,k,l,ismpl) + d2 = conc(i,j,k,l,ismpl) - conc(i,j,k-1,l,ismpl) + szc = amean(-dk(i,j,k,l,ismpl)*d1,-dk(i,j,k-1,l,ismpl)*d2) + ELSE IF (k==1) THEN + szc = -dk(i,j,k,l,ismpl)*(conc(i,j,k+1,l,ismpl)-conc(i,j,k,l & + ,ismpl)) + ELSE IF (k==k0) THEN + szc = -dk(i,j,k-1,l,ismpl)*(conc(i,j,k,l,ismpl)-conc(i,j,k-1 & + ,l,ismpl)) + END IF + + RETURN + END + +!> @brief average effective diffusivities on cell faces in x direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species +!> @param[in] ismpl local sample index +!> @return effective diffusivities (J/mK) + DOUBLE PRECISION FUNCTION di(i,j,k,spec,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + INTEGER spec + DOUBLE PRECISION f1, f2, prod, summ, betx, bety, betz, bet + DOUBLE PRECISION por, disp, vx, vy, vz + EXTERNAL por, disp, vx, vy, vz + + di = 0.D0 + betx = 0.D0 + bety = 0.D0 + betz = 0.D0 + IF (k0>1 .AND. k<k0) THEN + betz = vz(i,j,k,ismpl) + betz = betz*betz + END IF + IF (j0>1 .AND. j<j0) THEN + bety = vy(i,j,k,ismpl) + bety = bety*bety + END IF + IF (i0>1 .AND. i<i0) THEN + betx = vx(i,j,k,ismpl) + betx = betx*betx + bet = SQRT(betx + bety + betz) + f1 = por(i,j,k,ismpl)*diff_c(spec) + disp(i,j,k,ismpl)*bet + f2 = por(i+1,j,k,ismpl)*diff_c(spec) + & + disp(i+1,j,k,ismpl)*bet + prod = f1*f2 + summ = f1*delx(i+1) + f2*delx(i) + IF (summ>0.D0) di = 2.D0*prod/summ + END IF + + RETURN + END + +!> @brief average effective diffusivities on cell faces in y direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species +!> @param[in] ismpl local sample index +!> @return effective diffusivities (J/mK) + DOUBLE PRECISION FUNCTION dj(i,j,k,spec,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + INTEGER spec + DOUBLE PRECISION f1, f2, prod, summ, betx, bety, betz, bet + DOUBLE PRECISION por, disp, vy, vx, vz + EXTERNAL por, disp, vy, vx, vz + + dj = 0.D0 + betx = 0.D0 + bety = 0.D0 + betz = 0.D0 + IF (k0>1 .AND. k<k0) THEN + betz = vz(i,j,k,ismpl) + betz = betz*betz + END IF + IF (i0>1 .AND. i<i0) THEN + betx = vx(i,j,k,ismpl) + betx = betx*betx + END IF + IF (j0>1 .AND. j<j0) THEN + bety = vy(i,j,k,ismpl) + bety = bety*bety + bet = SQRT(betx + bety + betz) + f1 = por(i,j,k,ismpl)*diff_c(spec) + disp(i,j,k,ismpl)*bet + f2 = por(i,j+1,k,ismpl)*diff_c(spec) + & + disp(i,j+1,k,ismpl)*bet + prod = f1*f2 + summ = f1*dely(j+1) + f2*dely(j) + IF (summ>0.D0) dj = 2.D0*prod/summ + END IF + + RETURN + END + +!> @brief average effective diffusivities on cell faces in z direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species +!> @param[in] ismpl local sample index +!> @return effective diffusivities (J/mK) + DOUBLE PRECISION FUNCTION dk(i,j,k,spec,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: i, j, k + integer :: ismpl + INTEGER spec + DOUBLE PRECISION f1, f2, prod, summ, betx, bety, betz, bet + DOUBLE PRECISION por, disp, vz, vy, vx + EXTERNAL por, disp, vz, vy, vx + + dk = 0.D0 + betx = 0.D0 + bety = 0.D0 + betz = 0.D0 + IF (j0>1 .AND. j<j0) THEN + bety = vy(i,j,k,ismpl) + bety = bety*bety + END IF + IF (i0>1 .AND. i<i0) THEN + betx = vx(i,j,k,ismpl) + betx = betx*betx + END IF + IF (k0>1 .AND. k<k0) THEN + betz = vz(i,j,k,ismpl) + betz = betz*betz + bet = SQRT(betx + bety + betz) + f1 = por(i,j,k,ismpl)*diff_c(spec) + disp(i,j,k,ismpl)*bet + f2 = por(i,j,k+1,ismpl)*diff_c(spec) + & + disp(i,j,k+1,ismpl)*bet + prod = f1*f2 + summ = f1*delz(k+1) + f2*delz(k) + IF (summ>0.D0) dk = 2.D0*prod/summ + END IF + + RETURN + END diff --git a/forward/conc/neumann_conc.f90 b/forward/conc/neumann_conc.f90 new file mode 100644 index 0000000..ec981b6 --- /dev/null +++ b/forward/conc/neumann_conc.f90 @@ -0,0 +1,215 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_neumann_conc" +!> @param[out] neumann_max neumann criteria +!> @param[in] ismpl local sample index + SUBROUTINE neumann_conc(neumann_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION neumann_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_neumann_conc(neumann_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate grid neuman numbers (transport) +!> @param[out] neumann_max neumann criteria +!> @param[in] ismpl local sample index + SUBROUTINE omp_neumann_conc(neumann_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_conc + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + INTEGER c1, c2, c3 + DOUBLE PRECISION neumann_maxx, neumann_minx, neumann_avgx + DOUBLE PRECISION neumann_maxy, neumann_miny, neumann_avgy, neumann_maxz + DOUBLE PRECISION neumann_minz, neumann_avgz + DOUBLE PRECISION val, neumann_max, delt, fac, davg + DOUBLE PRECISION deltat + EXTERNAL deltat + + DOUBLE PRECISION di, dj, dk, por + EXTERNAL di, dj, dk, por + + INTEGER ispec + + + delt = deltat(simtime(ismpl),ismpl) + + IF ( .NOT. (transient .AND. tr_switch(ismpl))) THEN +!$OMP master + WRITE(*,*) ' neumann-conc: not defined for steady state' +!$OMP end master + RETURN + ELSE IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... neumann-conc: delt/tunit = ', & + delt/tunit + WRITE(*,*) +!$OMP end master + END IF + +! --------- species --------- + DO ispec = 1, ntrans + + c1 = 0 + neumann_maxx = small + neumann_minx = big + neumann_avgx = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + fac = delt/por(i,j,k,ismpl) + val = fac*di(i,j,k,ispec,ismpl)/(davg*davg) + IF (val>neumann_maxx) neumann_maxx = val + IF (val<neumann_minx) neumann_minx = val + neumann_avgx = neumann_avgx + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in y + c2 = 0 + neumann_maxy = small + neumann_miny = big + neumann_avgy = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + fac = delt/por(i,j,k,ismpl) + val = fac*dj(i,j,k,ispec,ismpl)/(davg*davg) + IF (val>neumann_maxy) neumann_maxy = val + IF (val<neumann_miny) neumann_miny = val + neumann_avgy = neumann_avgy + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in z + c3 = 0 + neumann_maxz = small + neumann_minz = big + neumann_avgz = 0.0D0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + fac = delt/por(i,j,k,ismpl) + val = fac*dk(i,j,k,ispec,ismpl)/(davg*davg) + IF (val>neumann_maxz) neumann_maxz = val + IF (val<neumann_minz) neumann_minz = val + neumann_avgz = neumann_avgz + val + END DO + END DO + END DO +!$OMP end do nowait + +! compute global sum for all values + CALL omp_summe(neumann_maxx,neumann_minx,neumann_avgx, & + neumann_maxy,neumann_miny,neumann_avgy,neumann_maxz, & + neumann_minz,neumann_avgz,c1,c2,c3,ismpl) + +!$OMP master + IF (i0>2) THEN + neumann_avgx = neumann_avgx/dble(c1) + ELSE + neumann_maxx = 0.0D0 + neumann_minx = 0.0D0 + neumann_avgx = 0.0D0 + END IF + IF (j0>2) THEN + neumann_avgy = neumann_avgy/dble(c2) + ELSE + neumann_maxy = 0.0D0 + neumann_miny = 0.0D0 + neumann_avgy = 0.0D0 + END IF + IF (k0>2) THEN + neumann_avgz = neumann_avgz/dble(c3) + ELSE + neumann_maxz = 0.0D0 + neumann_minz = 0.0D0 + neumann_avgz = 0.0D0 + END IF + + neumann_max = max(neumann_maxx,neumann_maxy,neumann_maxz) + + IF (linfos(3)>=2) THEN + WRITE(*,'(1A,1I3,1A)') & + ' neumann number for transport (species ', ispec, & + ') in x,y,z:' + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' max. : ', & + neumann_maxx, ', ', neumann_maxy, ', ', & + neumann_maxz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' min. : ', & + neumann_minx, ', ', neumann_miny, ', ', & + neumann_minz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + neumann_avgx, ', ', neumann_avgy, ', ', & + neumann_avgz + END IF + + IF (linfos(3)>=1 .AND. neumann_max>1.D0) THEN + WRITE(*,'(1A,1I3,1A)') & + '!!!: neumann temp number (species ', ispec, & + ') greater than 1 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + neumann_maxx, 'y: ', neumann_maxy, 'z: ', neumann_maxz + WRITE(*,*) + END IF +!$OMP end master + + END DO +! --------- species --------- + + RETURN + END diff --git a/forward/conc/peclet_conc.f90 b/forward/conc/peclet_conc.f90 new file mode 100644 index 0000000..ab8b56a --- /dev/null +++ b/forward/conc/peclet_conc.f90 @@ -0,0 +1,226 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_peclet_conc" +!> @param[out] peclet_max peclet number/criteria +!> @param[in] ismpl local sample index + SUBROUTINE peclet_conc(peclet_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION peclet_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_peclet_conc(peclet_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif +! + RETURN + END + +!> @brief calculate grid peclet numbers (transport) +!> @param[out] peclet_max peclet number/criteria +!> @param[in] ismpl local sample index + SUBROUTINE omp_peclet_conc(peclet_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_conc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + INTEGER c1, c2, c3 + DOUBLE PRECISION peclet_maxx, peclet_minx, peclet_avgx, & + peclet_maxy, peclet_miny, peclet_avgy, peclet_maxz, & + peclet_minz, peclet_avgz, val, davg, peclet_max + INTEGER ipt, jpt, kpt + DOUBLE PRECISION di, dj, dk, vx, vy, vz, por + EXTERNAL di, dj, dk, vx, vy, vz, por + INTEGER ispec + + IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... peclet-conc' + WRITE(*,*) +!$OMP end master + END IF +! +! -------- species -------- + DO ispec = 1, ntrans +! temperature-val in x + peclet_maxx = small + peclet_minx = big + peclet_avgx = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c1 = 0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + val = abs(vx(i,j,k,ismpl))*davg/di(i,j,k,ispec,ismpl) + IF (val>peclet_maxx) THEN + peclet_maxx = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_minx) peclet_minx = val + peclet_avgx = peclet_avgx + val + END DO + END DO + END DO +!$OMP end do nowait +! if (linfos(3).ge.2)write(*,*) +! & "max. temp-val in x: ", ipt,jpt,kpt +! +! temperature-val in y + peclet_maxy = small + peclet_miny = big + peclet_avgy = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c2 = 0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + val = abs(vy(i,j,k,ismpl))*davg/dj(i,j,k,ispec,ismpl) + IF (val>peclet_maxy) THEN + peclet_maxy = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_miny) peclet_miny = val + peclet_avgy = peclet_avgy + val + END DO + END DO + END DO +!$OMP end do nowait +! if(linfos(3).ge.2) +! & write(*,*)"max. temp-val in y: " ,ipt,jpt,kpt +! +! temperature-val in z + peclet_maxz = small + peclet_minz = big + peclet_avgz = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c3 = 0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + val = abs(vz(i,j,k,ismpl))*davg/dk(i,j,k,ispec,ismpl) + IF (val>peclet_maxz) THEN + peclet_maxz = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_minz) peclet_minz = val + peclet_avgz = peclet_avgz + val + END DO + END DO + END DO +!$OMP end do nowait +! if(linfos(3).ge.2) +! & write(*,*)"max. temp-val in z: " ,ipt,jpt,kpt +! +! compute global sum for all values + CALL omp_summe(peclet_maxx,peclet_minx,peclet_avgx, & + peclet_maxy,peclet_miny,peclet_avgy,peclet_maxz, & + peclet_minz,peclet_avgz,c1,c2,c3,ismpl) +! +!$OMP master + IF (i0>2) THEN + peclet_avgx = peclet_avgx/dble(c1) + ELSE + peclet_maxx = 0.0D0 + peclet_minx = 0.0D0 + peclet_avgx = 0.0D0 + END IF + IF (j0>2) THEN + peclet_avgy = peclet_avgy/dble(c2) + ELSE + peclet_maxy = 0.0D0 + peclet_miny = 0.0D0 + peclet_avgy = 0.0D0 + END IF + IF (k0>2) THEN + peclet_avgz = peclet_avgz/dble(c3) + ELSE + peclet_maxz = 0.0D0 + peclet_minz = 0.0D0 + peclet_avgz = 0.0D0 + END IF +! + peclet_max = max(peclet_avgx,peclet_avgy,peclet_avgz) +! + IF (linfos(3)>=2) THEN + WRITE(*,'(1A,1I3,1A)') & + ' peclet number for transport (species ', ispec, & + ') in x,y,z:' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' max. : ', & + peclet_maxx, ', ', peclet_maxy, ', ', peclet_maxz + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' min. : ', & + peclet_minx, ', ', peclet_miny, ', ', peclet_minz + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + peclet_avgx, ', ', peclet_avgy, ', ', peclet_avgz + END IF +! + IF (peclet_max>2.0D0 .AND. linfos(3)>=1) THEN + WRITE(*,'(1A,1I3,1A)') & + '!!!: peclet number for transport (species ', ispec, & + ' > 2 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + peclet_maxx, 'y: ', peclet_maxy, 'z: ', peclet_maxz + END IF +!$OMP end master +! + END DO +! -------- species -------- +! + RETURN + END diff --git a/forward/conc/set_cbc.f90 b/forward/conc/set_cbc.f90 new file mode 100644 index 0000000..3bfef03 --- /dev/null +++ b/forward/conc/set_cbc.f90 @@ -0,0 +1,226 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the species equation according to the boundary +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the species equation according to the boundary conditions\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_cbc(spec,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_conc + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype, i_dir, spec, i_spec + DOUBLE PRECISION val, malfa, mbeta, vx, vy, vz, dv, ds, vv + EXTERNAL vx, vy, vz + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! flow due to flow neumann nodes / wellars - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "neumann"?, skip otherwise + IF (bctype==bt_neum.OR.bctype==bt_neuw) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + +! wellar test + IF (val<0.0D0 .AND. tpbcu>=0) THEN + ds = 0.D0 + dv = 0.D0 + IF (i>1) THEN + vv = abs(vx(i-1,j,k,ismpl)) + ds = ds + vv + dv = dv + conc(i-1,j,k,spec,ismpl)*vv + END IF + IF (i<i0) THEN + vv = abs(vx(i,j,k,ismpl)) + ds = ds + vv + dv = dv + conc(i+1,j,k,spec,ismpl)*vv + END IF + IF (j>1) THEN + vv = abs(vy(i,j-1,k,ismpl)) + ds = ds + vv + dv = dv + conc(i,j-1,k,spec,ismpl)*vv + END IF + IF (j<j0) THEN + vv = abs(vy(i,j,k,ismpl)) + ds = ds + vv + dv = dv + conc(i,j+1,k,spec,ismpl)*vv + END IF + IF (k>1) THEN + vv = abs(vz(i,j,k-1,ismpl)) + ds = ds + vv + dv = dv + conc(i,j,k-1,spec,ismpl)*vv + END IF + IF (k<k0) THEN + vv = abs(vz(i,j,k,ismpl)) + ds = ds + vv + dv = dv + conc(i,j,k+1,spec,ismpl)*vv + END IF + dv = dv/ds +! apply dirichlet update [dv] +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*dv +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = dv + conc(i,j,k,spec,ismpl) = dv +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_conc, last_conc + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) + i_spec = ibc_data(ib,cbc_si) +! "dirichlet" and "spec"?, skip otherwise + IF (bctype==bt_diri .AND. i_spec==spec) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_cbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*val +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = val + conc(i,j,k,spec,ismpl) = val +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! neumann nodes - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_conc, last_conc + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) + i_spec = ibc_data(ib,cbc_si) + i_dir = ibc_data(ib,cbc_dir) +! "neumann" and "spec"?, skip otherwise + IF (bctype==bt_neum .AND. i_spec==spec) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_cbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN + IF ((i_dir==0)) val = val/(delx(i)*dely(j)*delz(k)) + IF ((i_dir==1) .OR. (i_dir==2)) val = val/delx(i) + IF ((i_dir==3) .OR. (i_dir==4)) val = val/dely(j) + IF ((i_dir==5) .OR. (i_dir==6)) val = val/delz(k) + + w(i,j,k,ismpl) = w(i,j,k,ismpl) - val + END IF + END IF + END DO + + RETURN + END diff --git a/forward/conc/set_ccoef.f90 b/forward/conc/set_ccoef.f90 new file mode 100644 index 0000000..dd9f350 --- /dev/null +++ b/forward/conc/set_ccoef.f90 @@ -0,0 +1,275 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate coefficents for the transport equation +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the transport equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_ccoef(spec,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_conc + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: i, j, k + integer :: ismpl + DOUBLE PRECISION di, dj, dk, por, vx, vy, vz, alfa + EXTERNAL di, dj, dk, por, vx, vy, vz, alfa + DOUBLE PRECISION v2, de, alf, p2 + INTEGER spec +!debug write(99,'(a,3i4)') 'ShemSUITE i0,j0,k0:',i0,j0,k0 + + +!$OMP master + IF (linfos(3)>=2) WRITE(*,*) ' ... ccoef' +!$OMP end master + +! inner points of grid - - - - - - - - - - - - - - - - - - - - - - - - - + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + + IF (i0>1) THEN + IF (i<i0) THEN + de = di(i,j,k,spec,ismpl) + v2 = 0.5D0*vx(i,j,k,ismpl) + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + alf = 0.D0 + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + e(i,j,k,ismpl) = (de-(1.D0-alf)*v2)/delx(i) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de+(1.D0+alf)*v2)/delx(i) + END IF + + IF (i>1) THEN + de = di(i-1,j,k,spec,ismpl) + v2 = 0.5*vx(i-1,j,k,ismpl) + alf = 0.D0 + IF (v2==0.D0) THEN + alf = 0.D0 + ELSE + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + END IF + + c(i,j,k,ismpl) = (de+(1.D0+alf)*v2)/delx(i) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de-(1.D0-alf)*v2)/delx(i) + END IF + END IF + + + + IF (j0>1) THEN + + IF (j<j0) THEN + + de = dj(i,j,k,spec,ismpl) + v2 = 0.5*vy(i,j,k,ismpl) + alf = 0.D0 + IF (v2==0.D0) THEN + alf = 0.D0 + ELSE + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + END IF + + f(i,j,k,ismpl) = (de-(1.D0-alf)*v2)/dely(j) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de+(1.D0+alf)*v2)/dely(j) + END IF + + + IF (j>1) THEN + + de = dj(i,j-1,k,spec,ismpl) + v2 = 0.5*vy(i,j-1,k,ismpl) + alf = 0.D0 + IF (v2==0.D0) THEN + alf = 0.D0 + ELSE + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + END IF + + b(i,j,k,ismpl) = (de+(1.D0+alf)*v2)/dely(j) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de-(1.D0-alf)*v2)/dely(j) + END IF + END IF + + IF (k0>1) THEN + + IF (k<k0) THEN + + de = dk(i,j,k,spec,ismpl) + v2 = 0.5D0*vz(i,j,k,ismpl) + alf = 0.D0 + IF (v2==0.D0) THEN + alf = 0.D0 + ELSE + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + END IF + + g(i,j,k,ismpl) = (de-(1.D0-alf)*v2)/delz(k) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de+(1.D0+alf)*v2)/delz(k) + END IF + + IF (k>1) THEN + + de = dk(i,j,k-1,spec,ismpl) + v2 = 0.5D0*vz(i,j,k-1,ismpl) + alf = 0.D0 + IF (v2==0.D0) THEN + alf = 0.D0 + ELSE + IF (de>0.D0) THEN + p2 = v2/de + alf = alfa(p2) + ELSE + IF (v2<0.D0) alf = -1.D0 + IF (v2>0.D0) alf = 1.D0 + END IF + END IF + + a(i,j,k,ismpl) = (de+(1.D0+alf)*v2)/delz(k) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (de-(1.D0-alf)*v2)/delz(k) + + END IF + + END IF + + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END + +!> @brief coefficents for the transport equation (here only the right side) +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the transport equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_ccoefrs(spec,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_conc + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + ! DOUBLE PRECISION rhoceff + DOUBLE PRECISION deltt + ! INTEGER c1, c2, c3, c4 + INTEGER spec + DOUBLE PRECISION deltat, por + EXTERNAL deltat, por + + + deltt = deltat(simtime(ismpl),ismpl) + +! - - rhs: sources, also terms for transient calculations - - - - - - - - - + + IF (transient .AND. tr_switch(ismpl)) THEN + +! - - - - - - - transient - - - - - - - - - - - - - - - - - - - - - - - - - + CALL omp_mvp(i0,j0,k0,concold(1,spec,cgen_time,ismpl), & + x(1,1,1,ismpl),a(1,1,1,ismpl),b(1,1,1,ismpl), & + c(1,1,1,ismpl),d(1,1,1,ismpl),e(1,1,1,ismpl), & + f(1,1,1,ismpl),g(1,1,1,ismpl)) + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + por(i,j,k,ismpl)/(deltt*thetac) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + por(i,j,k,ismpl)*concold(i+(j-1)*i0+(k-1)*i0*j0, & + spec,cgen_time,ismpl)/deltt - & + (1.D0-thetac)*x(i,j,k,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl)/thetac + END DO + END DO + END DO +!$OMP end do nowait + + ELSE + +! - - - - - - - - steady state - - - - - - - - - - - - - - - - - - - - - +! C$OMP do schedule(static) collapse(3) +! do k=1,k0 +! do j=1,j0 +! do i=1,i0 +! w(i,j,k,ismpl) = w(i,j,k,ismpl) +! - hs(i,j,k,spec,ismpl) +! end do +! end do +! end do +! C$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/conc/set_cq.f90 b/forward/conc/set_cq.f90 new file mode 100644 index 0000000..b80014c --- /dev/null +++ b/forward/conc/set_cq.f90 @@ -0,0 +1,66 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for a concentration equation according to the prescribed sources and sinks +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for a concentration equation according to the prescribed sources and sinks.\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_cq(spec,ismpl) + use arrays + use mod_genrl + use mod_time + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + INTEGER spec + DOUBLE PRECISION deltat, deltf, qc + EXTERNAL deltat, qc + +! rhs: sources + IF (transient .AND. tr_switch(ismpl)) THEN + deltf = deltat(simtime(ismpl),ismpl) +!$OMP do schedule (static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qc(i,j,k,spec,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + ELSE +!$OMP do schedule (static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qc(i,j,k,spec,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/converged.f90 b/forward/converged.f90 new file mode 100644 index 0000000..821aa45 --- /dev/null +++ b/forward/converged.f90 @@ -0,0 +1,157 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute average for break condition +!> @param[in] enough test for break +!> @param[in] depsilon break condition +!> @param[in] Htype history (number) +!> @param[in] maxhistlen max history length +!> @param[in] history HISTORY buffer +!> @param[in] hlen History Length +!> @param[in] ipos Position Index +!> @param[in] Hmax history length +!> @return "true" when converged +!> @details +!> proof "enough" < "depsilon" or the average of the last "hlen" steps\n + LOGICAL FUNCTION converged(enough,depsilon,htype,maxhistlen,hmax,history,hlen,ipos) + + USE mod_genrl + use mod_linfos + + IMPLICIT NONE + + ! step diff. or precision + DOUBLE PRECISION enough + + ! break condition + DOUBLE PRECISION depsilon + + ! max history length + INTEGER maxhistlen + + ! number of probes for each history length + INTEGER maxprob + PARAMETER (maxprob=4) + + ! History (selection, counter, number) + INTEGER htype, h, hmax + + ! HISTORY buffer + DOUBLE PRECISION history(maxhistlen,hmax) + + ! History Length + INTEGER hlen(hmax) + + ! Position Index + INTEGER ipos(hmax) + + ! locale SUM for average computation + DOUBLE PRECISION lsum, smin, smax + + ! loop Index + INTEGER i + + ! Wrong htype values + IF (htype==0) THEN + WRITE(*,*) & + 'error: "history type"=0 in "converged" not allowed !' + STOP + END IF + IF (htype>hmax) THEN + WRITE(*,*) 'error: "history number" (Hmax<', htype, & + ') in "converged" to low !' + STOP + END IF + + ! nonlinear convergence test is disabled by input file + IF (.NOT. nlconverge .eq. 0) THEN + converged = .FALSE. + RETURN + END IF + + ! quick test: maximum difference smaller than tolerance + IF (abs(enough)<depsilon) THEN + converged = .TRUE. + RETURN + END IF + + ! set defaults + converged = .FALSE. + h = htype + IF (htype<0) THEN + ! init iterations, then end + h = -htype + hlen(h) = 1 + ipos(h) = -1 + RETURN + END IF + + ! break, if history buffer too small + IF (ipos(h)>=maxprob*maxhistlen) THEN + WRITE(*,*) 'warning: history buffer in "converged.f"', & + ' to small ! <break outer iterations>' + converged = .TRUE. + END IF + + ! fill history with new element + IF (ipos(h)>=maxprob*hlen(h)) THEN + + ! increase history length + hlen(h) = hlen(h) + 1 + ipos(h) = -1 + history(hlen(h),h) = enough + + ELSE + + ! Add position + ipos(h) = ipos(h) + 1 + history(1+mod(ipos(h),hlen(h)),h) = enough + + END IF + + ! compute sum for average + lsum = 0.0D0 + smin = history(1,h) + smax = history(1,h) + DO i = 1, hlen(h) + lsum = lsum + history(i,h) + smin = min(smin,history(i,h)) + smax = max(smax,history(i,h)) + END DO + +! can we break iterations (enough precision) + IF ((abs(lsum)/dble(hlen(h)))<depsilon) converged = .TRUE. + + IF ((abs(enough)>depsilon) .AND. (converged)) THEN + IF (h==1) WRITE(*,'(2(A,1e15.8),A,I3)') & + 'warning: oscillating convergence in HEAD, [min:max] = [', & + smin, ':', smax, '], period length=', hlen(h) + IF (h==2) WRITE(*,'(2(A,1e15.8),A,I3)') & + 'warning: oscillating convergence in TEMP, [min:max] = [', & + smin, ':', smax, '], period length=', hlen(h) + IF (h>=4) WRITE(*,'(2(A,1e15.8),A,I3)') & + 'warning: oscillating convergence in CONC, [min:max] = [', & + smin, ':', smax, '], period length=', hlen(h) + END IF + + RETURN + END diff --git a/forward/courant.f90 b/forward/courant.f90 new file mode 100644 index 0000000..0f414a1 --- /dev/null +++ b/forward/courant.f90 @@ -0,0 +1,200 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_courant" +!> @param[out] courant_max global courant number +!> @param[in] ismpl local sample index + SUBROUTINE courant(courant_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION courant_max + integer :: ismpl + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_courant(courant_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate grid courant number +!> @param[out] courant_max global courant number +!> @param[in] ismpl local sample index + SUBROUTINE omp_courant(courant_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: i, j, k + integer :: ismpl + + DOUBLE PRECISION courant_maxx, courant_minx, courant_avgx + DOUBLE PRECISION courant_maxy, courant_miny, courant_avgy, courant_maxz + DOUBLE PRECISION courant_minz, courant_avgz + DOUBLE PRECISION courant_max, fac, delt, deltat, davg, val, min_veloc + EXTERNAL deltat +! min. value, ignore courant numbers for lower velocities + PARAMETER (min_veloc=1.0D-10) +! + INTEGER c1, c2, c3 + DOUBLE PRECISION vx, vy, vz, por + EXTERNAL vx, vy, vz, por + + delt = deltat(simtime(ismpl),ismpl) +! + IF ( .NOT. (transient .AND. tr_switch(ismpl))) THEN +!$OMP master + WRITE(*,*) ' courant: not defined for steady state' +!$OMP end master + RETURN + END IF +! + c1 = 0 + courant_maxx = small + courant_minx = big + courant_avgx = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + val = abs(vx(i,j,k,ismpl)) + IF (val>=min_veloc) THEN + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + fac = delt/(davg*por(i,j,k,ismpl)) + val = val*fac + IF (val>courant_maxx) courant_maxx = val + IF (val<courant_minx) courant_minx = val + courant_avgx = courant_avgx + val + END IF + END DO + END DO + END DO +!$OMP end do nowait +! + c2 = 0 + courant_maxy = small + courant_miny = big + courant_avgy = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + val = abs(vy(i,j,k,ismpl)) + IF (val>=min_veloc) THEN + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + fac = delt/(davg*por(i,j,k,ismpl)) + val = val*fac + IF (val>courant_maxy) courant_maxy = val + IF (val<courant_miny) courant_miny = val + courant_avgy = courant_avgy + val + END IF + END DO + END DO + END DO +!$OMP end do nowait +! + c3 = 0 + courant_maxz = small + courant_minz = big + courant_avgz = 0.0D0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + val = abs(vz(i,j,k,ismpl)) + IF (val>=min_veloc) THEN + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + fac = delt/(davg*por(i,j,k,ismpl)) + val = val*fac + IF (val>courant_maxz) courant_maxz = val + IF (val<courant_minz) courant_minz = val + courant_avgz = courant_avgz + val + END IF + END DO + END DO + END DO +!$OMP end do nowait +! +! compute global sum for all values + CALL omp_summe(courant_maxx,courant_minx,courant_avgx, & + courant_maxy,courant_miny,courant_avgy,courant_maxz, & + courant_minz,courant_avgz,c1,c2,c3,ismpl) +! +!$OMP master + IF (i0>2) THEN + courant_avgx = courant_avgx/dble(c1) + ELSE + courant_maxx = 0.0D0 + courant_minx = 0.0D0 + courant_avgx = 0.0D0 + END IF + IF (j0>2) THEN + courant_avgy = courant_avgy/dble(c2) + ELSE + courant_maxy = 0.0D0 + courant_miny = 0.0D0 + courant_avgy = 0.0D0 + END IF + IF (k0>2) THEN + courant_avgz = courant_avgz/dble(c3) + ELSE + courant_maxz = 0.0D0 + courant_minz = 0.0D0 + courant_avgz = 0.0D0 + END IF +! + courant_max = max(courant_maxx,courant_maxy,courant_maxz) +! + IF (linfos(3)>=2) THEN + WRITE(*,*) 'courant-number in x,y,z:' + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' max. : ', & + courant_maxx, ', ', courant_maxy, ', ', courant_maxz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' min. : ', & + courant_minx, ', ', courant_miny, ', ', courant_minz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3,1a,3I8)') ' avg. : ', & + courant_avgx, ', ', courant_avgy, ', ', & + courant_avgz, ', #', c1, c2, c3 + END IF +! + IF (linfos(3)>=1 .AND. courant_max>1.D0) THEN + WRITE(*,'(a)') '!!!: courant number(s) greater than 1 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + courant_maxx, 'y: ', courant_maxy, 'z: ', courant_maxz + WRITE(*,*) + END IF +!$OMP end master + + RETURN + END diff --git a/forward/ctrlut/decntrl3.f90 b/forward/ctrlut/decntrl3.f90 new file mode 100644 index 0000000..1defefc --- /dev/null +++ b/forward/ctrlut/decntrl3.f90 @@ -0,0 +1,45 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief convert the number code ctrl0 (12bit) into 3 discrete numbers c1,c2,c3 (each 4bit) +!> @param[in] ctrl0 number code +!> @param[out] c1 first discrete value +!> @param[out] c2 second discrete value +!> @param[out] c3 third discrete value +!> @details +!> decode [ctrl]\n +!> ctrl = c1 + 16*c2 + 256*c3\n + SUBROUTINE decntrl3(ctrl0,c1,c2,c3) + IMPLICIT NONE + INTEGER ctrl, ctrl0, c1, c2, c3 +! + ctrl = ctrl0 + c1 = mod(ctrl,16) +! + ctrl = ctrl/16 + c2 = mod(ctrl,16) +! + ctrl = ctrl/16 + c3 = mod(ctrl,16) +! + RETURN + END diff --git a/forward/ctrlut/decntrl4.f90 b/forward/ctrlut/decntrl4.f90 new file mode 100644 index 0000000..c45c3c0 --- /dev/null +++ b/forward/ctrlut/decntrl4.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief convert the number code ctrl0 (16bit) into 4 discrete numbers c1,c2,c3,c4 (each 4bit) +!> @param[in] ctrl0 number code +!> @param[out] c1 first discrete value +!> @param[out] c2 second discrete value +!> @param[out] c3 third discrete value +!> @param[out] c4 fourth discrete value +!> @details +!> decode [ctrl]\n +!> ctrl = c1 + 16*c2 + 256*c3 + 4096*c4\n + SUBROUTINE decntrl4(ctrl0,c1,c2,c3,c4) + IMPLICIT NONE + INTEGER ctrl, ctrl0, c1, c2, c3, c4 +! + ctrl = ctrl0 + c1 = mod(ctrl,16) +! + ctrl = ctrl/16 + c2 = mod(ctrl,16) +! + ctrl = ctrl/16 + c3 = mod(ctrl,16) +! + ctrl = ctrl/16 + c4 = mod(ctrl,16) +! + RETURN + END diff --git a/forward/ctrlut/encntrl3.f90 b/forward/ctrlut/encntrl3.f90 new file mode 100644 index 0000000..b1fabd5 --- /dev/null +++ b/forward/ctrlut/encntrl3.f90 @@ -0,0 +1,35 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief convert 3 discrete numbers c1,c2,c3 (each 4bit) into the number code ctrl0 (12bit) +!> @param[out] ctrl number code +!> @param[in] c1 first discrete value +!> @param[in] c2 second discrete value +!> @param[in] c3 third discrete value + SUBROUTINE encntrl3(ctrl,c1,c2,c3) + IMPLICIT NONE + INTEGER ctrl, c1, c2, c3 +! + ctrl = c1 + 16*c2 + 256*c3 +! + RETURN + END diff --git a/forward/ctrlut/encntrl4.f90 b/forward/ctrlut/encntrl4.f90 new file mode 100644 index 0000000..1eefb1c --- /dev/null +++ b/forward/ctrlut/encntrl4.f90 @@ -0,0 +1,36 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief convert 4 discrete numbers c1,c2,c3,c4 (each 4bit) into the number code ctrl0 (16bit) +!> @param[out] ctrl number code +!> @param[in] c1 first discrete value +!> @param[in] c2 second discrete value +!> @param[in] c3 third discrete value +!> @param[in] c4 fourth discrete value + SUBROUTINE encntrl4(ctrl,c1,c2,c3,c4) + IMPLICIT NONE + INTEGER ctrl, c1, c2, c3, c4 +! + ctrl = c1 + 16*c2 + 256*c3 + 4096*c4 +! + RETURN + END diff --git a/forward/ctrlut/ijk_m.f90 b/forward/ctrlut/ijk_m.f90 new file mode 100644 index 0000000..05a0ee3 --- /dev/null +++ b/forward/ctrlut/ijk_m.f90 @@ -0,0 +1,91 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute "i,j,k"-index of "m", depending on "i0,j0,k0" +!> @param[in] m continuous memory cell-index +!> @param[out] i cell index, direction I0 +!> @param[out] j cell index, direction J0 +!> @param[out] k cell index, direction K0 +!> @details +!> Compute k cell index: \n\n +!> +!> k = (m-1) / (i0*j0) + 1 \n\n +!> +!> Explanations:\n +!> 1) m-1: The integer steps between k-indices are at elements m = +!> n*(i0*j0 + 1) for some positive integer n [f.e.: m=i0*j0 is +!> still in the lowest layer, m=i0*j0+1 is in the second lowest +!> layer]. The steps of the division are at m_div = n*(i0*j0). \n +!> 2) +1 at end: The division gives k = 0 for the lowest layer, k = 1 +!> for the second-lowest, and so on. The layer-counting starts at +!> k=1, so 1 is added. \n\n +!> +!> Compute j cell index: \n\n +!> +!> j = (m-1 - (k-1)*i0*j0) / i0 + 1 \n\n +!> +!> Explanations:\n +!> 1) (m-1 - (k-1)*i0*j0): The index is projected onto its +!> partner-index on the lowest layer by subtracting the number of +!> z-layers on top, then one is subtracted, since the steps between +!> j-indices should be at m=n*(i0+1), but the steps of the division +!> by i0 are at m=n*i0. \n +!> 2) +1 at end: The division by i0 gives j = 0 for the first line in +!> x-direction, j = 1 for the second, and so on. The line-counting +!> should start at j=1, so 1 is added. \n\n +!> +!> Compute i cell index: \n\n +!> +!> i = m - (k-1)*i0*j0 - (j-1)*i0\n\n +!> +!> Explanations:\n +!> 1) (m - (k-1)*i0*j0): The index is projected onto its +!> partner-index on the lowest layer by subtracting the number of +!> z-layers on top. \n +!> 2) - (j-1)*i0: The index is projected onto its +!> partner-index on the first line by subtracting the number of +!> y-lines . \n\n + subroutine ijk_m(m,i,j,k) + + use mod_genrl, only: i0, j0, k0 + + implicit none + + ! Continuous linear index + integer, intent (in) :: m + + ! i-cell/j-cell/k-cell index + integer, intent (out) :: i, j, k + + + ! Compute k-cell index + k = (m-1) / (i0*j0) + 1 + + ! Compute j-cell index + j = (m-1 - (k-1)*i0*j0) / i0 + 1 + + ! Compute i-cell index + i = m - (k-1)*i0*j0 - (j-1)*i0 + + return + + end subroutine ijk_m diff --git a/forward/ctrlut/m_ijk.f90 b/forward/ctrlut/m_ijk.f90 new file mode 100644 index 0000000..fafb7cf --- /dev/null +++ b/forward/ctrlut/m_ijk.f90 @@ -0,0 +1,36 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute "m" of "i,j,k"-index, depending on "i0,j0,k0" +!> @param[out] m continuous memory cell-index +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 + SUBROUTINE m_ijk(i,j,k,m) + use mod_genrl + IMPLICIT NONE + integer :: i, j, k, m +! + m = i+(j-1)*i0+(k-1)*i0*j0 +! + RETURN + END diff --git a/forward/dealloc_arrays.f90 b/forward/dealloc_arrays.f90 new file mode 100644 index 0000000..cf0cc7c --- /dev/null +++ b/forward/dealloc_arrays.f90 @@ -0,0 +1,245 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief free the memory of all global main arrays (with dynamic size) +!> @param[in] ismpl local sample index + SUBROUTINE dealloc_arrays(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_conc + use mod_linfos + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + INTEGER mfactor + INTRINSIC max + +! + IF (linfos(1)>=2) WRITE(*,*) ' [I] : ... dealloc_arrays' +! +! single system size (factor == 1) + mfactor = 1 + + DEALLOCATE(project_sfx) + + DEALLOCATE(propunit) + memory = memory - nunits*nprop*nsmpl + +! temporary convergence list + DEALLOCATE(conc_conv) + memory = memory - ntrac*nsmpl + + DEALLOCATE(node_info) + memory = memory - i0*j0*k0 +! additional global & private vectors for linear system solver +! global buffer for boundary exchange (+ismpl) + DEALLOCATE(lss_bound_block) + memory = memory - (block_i*block_j+block_i*block_k+block_j*block_k)*bdim_i*bdim_j*bdim_k*2*nsmpl + DEALLOCATE(lss_dnrm) + memory = memory - i0*j0*k0*nsmpl + DEALLOCATE(lss_tmp) + memory = memory - i0*j0*k0*nsmpl +! private copy for preconditioning (+Tlevel_1 +ismpl) + DEALLOCATE(lss_lma) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lmb) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lmc) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lmd) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lme) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lmf) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lmg) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lud) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lx) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_lb) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl +! + DEALLOCATE(lss_lloctmp) + memory = memory - max_blocks*block_i*block_j*block_k*mfactor*max_loctmp*tlevel_1*nsmpl +! + DEALLOCATE(lss_ldnrm) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + DEALLOCATE(lss_ud_block) + memory = memory - (block_i*block_j+block_i*block_k+block_j*block_k)*max_blocks*tlevel_1*nsmpl + DEALLOCATE(lss_lr0_hat) + memory = memory - max_blocks*block_i*block_j*block_k*tlevel_1*nsmpl + +! variables for variable time stepping + deallocate(flag_delt) + memory = memory - nsmpl + deallocate(delt_count) + memory = memory - nsmpl + deallocate(flag_1st_timestep) + memory = memory - nsmpl + deallocate(delt_old) + memory = memory - nsmpl +! +! +! coefficients for linear equations + DEALLOCATE(a) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(b) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(c) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(d) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(e) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(f) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(g) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(x) + memory = memory - i0*j0*k0*mfactor*nsmpl +! + DEALLOCATE(w) + memory = memory - i0*j0*k0*mfactor*nsmpl + DEALLOCATE(r) + memory = memory - i0*j0*k0*mfactor + DEALLOCATE(bc_mask) + memory = memory - i0*j0*k0*mfactor*nsmpl +! only for ilu-precond. (shadow vectors) + DEALLOCATE(ud) + memory = memory - i0*j0*k0*mfactor*nsmpl +! +! + DEALLOCATE(head) + memory = memory - i0*j0*k0*nsmpl + DEALLOCATE(temp) + memory = memory - i0*j0*k0*nsmpl + DEALLOCATE(conc) + memory = memory - i0*j0*k0*max(ntrans,1)*nsmpl + DEALLOCATE(pres) + memory = memory - i0*j0*k0*nsmpl + DEALLOCATE(tsal) + memory = memory - i0*j0*k0*nsmpl + DEALLOCATE(uindex) + memory = memory - i0*j0*k0 + + DEALLOCATE(headold) + memory = memory - i0*j0*k0*ncgen*nsmpl + DEALLOCATE(tempold) + memory = memory - i0*j0*k0*ncgen*nsmpl + DEALLOCATE(concold) + memory = memory - i0*j0*k0*ncgen*nsmpl*max(ntrans,1) + DEALLOCATE(presold) + memory = memory - i0*j0*k0*ncgen*nsmpl + + DEALLOCATE(delx) + memory = memory - i0 + DEALLOCATE(dely) + memory = memory - j0 + DEALLOCATE(delz) + memory = memory - k0 + DEALLOCATE(delxa) + memory = memory - i0 + DEALLOCATE(delya) + memory = memory - j0 + DEALLOCATE(delza) + memory = memory - k0 + + if (vdefaultswitch) then + DEALLOCATE(vdefault) + end if + +! dealloc. proz. grid array, see more in 'solve/omp_preconditioniers.f' + CALL par_end2() + +! time periods + DEALLOCATE(bcperiod) + memory = memory - ngsmax*3*max(nbctp,1)*nsmpl + DEALLOCATE(ibcperiod) + memory = memory - max(nbctp,1) + DEALLOCATE(lbcperiod) + memory = memory - ngsmax*max(nbctp,1) + DEALLOCATE(outt) + memory = memory - max(noutt+1,1) + DEALLOCATE(smon_idx) + memory = memory - nsmpl + deallocate(delta_time) + memory = memory - max(ntimestep,1) + + DEALLOCATE(simtime) + memory = memory - nsmpl + + DEALLOCATE(tr_switch) + memory = memory - nsmpl + + DEALLOCATE(fh_table) + memory = memory - c_fhandler*tlevel_0 + + DEALLOCATE(diff_c) + memory = memory - max(ntrans,1) + DEALLOCATE(mmas_c) + memory = memory - max(ntrans,1) + DEALLOCATE(beta_c) + memory = memory - max(ntrans,1) + +! boundary structures + DEALLOCATE(ibc_data) + memory = memory - max(nbc_data,1)*nibc + DEALLOCATE(dbc_data) + memory = memory - max(nbc_data,1)*ndbc*nsmpl + DEALLOCATE(dbc_dataold) + memory = memory - max(nbc_data,1) + +! borehole logs + DEALLOCATE(ibh_pos) + memory = memory - 2*nbh_logs + DEALLOCATE(cbh_name) + memory = memory - nbh_logs*64 + +! - convergency history buffer - + DEALLOCATE(conv_history) + memory = memory - conv_hlen*conv_hmax*nsmpl + DEALLOCATE(conv_chlen) + DEALLOCATE(conv_ipos) + DEALLOCATE(lcon) + memory = memory - 3*conv_hmax*nsmpl + +#ifdef DEBUG + DEALLOCATE(debugout) + n_debugout = 0 +#endif + +! OpenMP specific REDUCTION staff + DEALLOCATE(omp_dglobal) + DEALLOCATE(omp_iglobal) + memory = memory - 12*tlevel_1*nsmpl + + + write(*,*) "Deallocated Memory, remaining ",memory*8/1024/1024, " MB" + RETURN + END SUBROUTINE dealloc_arrays diff --git a/forward/deltat.f90 b/forward/deltat.f90 new file mode 100644 index 0000000..6347e45 --- /dev/null +++ b/forward/deltat.f90 @@ -0,0 +1,220 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief get the size of the current time step +!> @param[in] sim_time current simulation time +!> @param[in] ismpl local sample index +!> @return deltat of the time step +!> @details +!> Return the deltat of the time step depending on the simulation time +!> [sim_time] and the time step table [delta_time]\n\n +!> +!> 1. Input time stepping: Add delta_time values until the cumulative +!> sum minus 1/100 times the last deltat is larger than the simulation +!> time input. Then, the final deltat is the output of the +!> function. \n\n +!> +!> 2. Variable time stepping: Set (a) the starting time step in the +!> beginning, (b) go back to the last simtime and half the previous +!> time step, when the nonlinear maxiter was reached, or (c) keep the +!> time step or double it if everything was alright, then look for the +!> maximum simulation time or upcoming output times and adjust the +!> time step accordingly. + double precision function deltat(sim_time,ismpl) + + use arrays, only: delta_time, flag_1st_timestep, delt_count, & + delt_old, flag_delt, simtime, outt + use mod_genrl, only: delt_double, delt_min, delt_max, delt_start, & + delt_vary + use mod_time, only: max_simtime, simtime_0, noutt, ntimestep + + implicit none + + double precision, intent (in) :: sim_time + + integer :: ismpl + + ! Counter + integer :: i + + ! Tolerance for sim_time smaller timesum + double precision :: tentol + + ! Cumulative sum of delta_time values + double precision :: timesum + + ! Time step counter + integer :: it + + ! Output time id + integer :: id + + if (.not. delt_vary) then + ! Time stepping from `# time periods` + ! ----------------------------------- + + deltat = 0.0d0 + + ! time step counter + it = 1 + + ! init time step size + deltat = delta_time(it) + + ! 1% numerical tolerance + tentol = 0.01d0*deltat + + ! init time sum + timesum = simtime_0 + deltat +! + do while (sim_time + tentol >= timesum .and. it < ntimestep) + it = it + 1 + ! update time step size + deltat = delta_time(it) + ! 1% numerical tolerance + tentol = 0.01d0*deltat + ! update time sum + timesum = timesum + deltat + end do + + else + ! Variable time stepping. + ! ----------------------- + + if (sim_time == simtime_0 .and. flag_1st_timestep(ismpl) == 0) then + + ! Set starting time step + deltat = delt_start + delt_old(ismpl) = deltat + delt_count(ismpl) = 0 + + else + + ! Set previous time step + deltat = delt_old(ismpl) + + end if + + if (flag_delt(ismpl) == -2) then + ! Iterative solver or Picard/Newton iteration reached maxiter + + !Restore old simulation time + simtime(ismpl) = simtime(ismpl) - delt_old(ismpl) + + flag_1st_timestep(ismpl) = 1 + + write(*,*) "Halfing time step!" + write(*,*) "Old deltat: ", deltat + + ! Half the time step size + deltat = 0.5*deltat + + write(*,*) "New deltat: ", deltat + + ! Check whether minimum deltat is reached + if (deltat < delt_min) then + write(*,*) "Minimum step size reached. Aborting." + write(unit = *, fmt = *) "Current deltat = ", deltat + write(unit = *, fmt = *) "Minimum deltat = ", delt_min + stop + end if + + else if (flag_delt(ismpl) == 1) then + ! Iterative solver or Picard/Newton iteration fine + + ! Counter closer to doubling + delt_count(ismpl) = delt_count(ismpl) + 1 + + ! Doubling time step size if delt_count hits delt_double + if (delt_count(ismpl) == delt_double) then + + ! Reset doubling counter + delt_count(ismpl) = 0 + + write(*,*) "Doubling time step size!" + write(*,*) "Old deltat: ", deltat + + ! Double the time step size. + deltat = 2*deltat + + write(*,*) "New deltat: ", deltat + + ! Check whether maximum delt is reached + if (deltat > delt_max) then + write(*,*) "Maximum deltat reached. No further timestep size increase possible." + deltat = delt_max + write(*,*) "deltat: ", deltat + write(*,*) "delt_max: ", delt_max + end if + end if + + ! Is max_simtime reached? + ! Info: add delt_old, because simtime update not yet realized + if ((simtime(ismpl) + delt_old(ismpl) + deltat) > max_simtime) then + write(*,*) "Changing step size to reach simulation end." + + ! Set deltat to reach max_simtime + deltat = max_simtime - simtime(ismpl)-delt_old(ismpl) + + write(*,*) "deltat: ", deltat + + end if + + ! Find the upcoming output time id + id = 0 + do i = 1, noutt +1 + + if (outt(i) > simtime(ismpl) + delt_old(ismpl) ) then + + id = i + exit + + end if + + end do + + ! Change deltat to match output time if output time is in + ! the next time step. + if ((simtime(ismpl) + delt_old(ismpl) + deltat) > outt(id)) then + + ! Match only if the new deltat is larger than 10 times + ! the minimum step size + if ((outt(id) - simtime(ismpl) - delt_old(ismpl)) > 10.0d0*delt_min) then + + deltat = outt(id) - simtime(ismpl) - delt_old(ismpl) + + write(*,*) "Changing deltat to match output time." + write(*,*) "deltat: ", deltat + + end if + + end if + + end if + + delt_old(ismpl) = deltat + + end if + + return + + end function deltat diff --git a/forward/forward_init.f90 b/forward/forward_init.f90 new file mode 100644 index 0000000..bc64a6f --- /dev/null +++ b/forward/forward_init.f90 @@ -0,0 +1,78 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief forward model initialisation +!> @param[in] ismpl local sample index +!> @details +!> - For the head-based model computation, the pressure may need to be +!> computed from head input. For the pres-based model computation, +!> the head may need to be computed from pressure input. \n\n +!> +!> - Call user and props initializing subroutines \n\n +!> +!> - output memory information\n + subroutine forward_init(ismpl) + + use mod_genrl, only: is_init_flow_trafo_needed, memory + use mod_linfos, only: linfos + + implicit none + + ! Local sample index + integer :: ismpl + + ! Local variable for array memory + double precision :: memloc + + + if (linfos(3)>=2) write(*,*) ' ... forward_init' + + ! If needed: Transformation to non-computed flow variable. +#ifdef head_base + if (is_init_flow_trafo_needed) call head2pres(0,ismpl) +#endif +#ifdef pres_base + if (is_init_flow_trafo_needed) call pres2head(0,ismpl) +#endif + + ! USER model init + call user_init(ismpl) + + ! PROPS model init + call props_init(ismpl) + + ! Memory information output + if (linfos(1)>=0) then + ! Assume double precision data type + memloc = memory*8.0D0 + ! ... in KByte + memloc = memloc/1024.0D0 + ! ... in MByte + memloc = memloc/1024.0D0 + write(*,*) '' + write(*,'(a,f11.3,a)') ' [I] : memory: ', memloc, ' MByte data' + write(*,*) '' + end if + + return + + end subroutine forward_init diff --git a/forward/forward_iter.f90 b/forward/forward_iter.f90 new file mode 100644 index 0000000..86ccbee --- /dev/null +++ b/forward/forward_iter.f90 @@ -0,0 +1,210 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief time discretisation loop +!> @param[in] simtime_run start time of the simulation +!> @param[in] simtime_end finish time of the simulation +!> @param[in] ismpl local sample index +!> @details +!> In-a-Nutshell description of this subroutine: \n +!> - Preprocessing before time step loop, initial variable values, +!> monitoring output, extra steady-state initialisation, status_log\n +!> - Time loop: \n +!> - before computations: time stepping, saving old variable arrays, +!> output \n +!> - computation: calling `forward_wrapper.f90` +!> - after computations: save simulated data, update simtime, +!> output, check divergence for variable step size \n +!> - Postprocessing: standard output + subroutine forward_iter(simtime_run,simtime_end,ismpl) + + use arrays, only: flag_1st_timestep, simtime, tr_switch, & + flag_delt + use mod_genrl, only: cgen_time, iter_nlold, maxiter_nl, runmode, & + write_iter_disable + use mod_genrlc, only: status_log + use mod_time, only: itimestep_0, max_simtime, monitor, simtime_0, & + transient, tunit + use mod_linfos, only: linfos + + implicit none + + ! local sample index + integer :: ismpl + + ! Time step index + integer :: itimestep + + ! Size of a time period + double precision :: deltt + + ! Start time of the simulation + double precision, intent (in) :: simtime_run + + ! Finish time of the simulation + double precision, intent (in) :: simtime_end + + double precision, external :: deltat + integer, external :: lblank + + + ! Preprocessing + ! ------------- + + ! initial values for some variables/arrays + flag_1st_timestep(ismpl)=0 + itimestep = itimestep_0 + simtime(ismpl) = simtime_run + deltt = deltat(simtime(ismpl),ismpl) + tr_switch(ismpl) = .true. + iter_nlold = maxiter_nl/2 + + ! initial monitoring output + if (transient .and. monitor .and. simtime_run == simtime_0) then + call write_monitor(1,ismpl) + call write_monitor_user(1,ismpl) + end if + + ! runmode 2: extra steady state initialisation + if (transient .and. runmode == 2) then + + tr_switch(ismpl) = .false. + if (linfos(2) >= 0) write(*,'(1A)') ' [I] : extra steady state initialisation' + + call forward_wrapper(itimestep,ismpl) + + if (linfos(2) >= 0) write(*,'(1A)') ' [I] : normal transient process' + tr_switch(ismpl) = .true. + + end if + + ! Write to status_log + if (transient .and. (.not. write_iter_disable)) then + + open(76, file=status_log, status='unknown', position='append') + write(76, fmt='(I8,1e14.6,1e14.6)') itimestep, deltt, simtime(ismpl)/tunit + close(76) + + end if + + ! Time step loop for forward modeling + ! ----------------------------------- +1000 CONTINUE + + if (transient) then + + ! Advance time step + itimestep = itimestep + 1 + + ! Initialize flag for variable time step size + flag_delt(ismpl) = 0 + + ! Time stepping info to standard out + if (linfos(1)>=1) then + write(*,*) ' ' + write(*,'(1A,1I6)') ' >>>> new time step: ', itimestep + write(*,'(1A,1e16.8,1A,1e16.8)') ' >>>> cum. time= ', & + (simtime(ismpl)+deltt)/tunit, '/', max_simtime/tunit + write(*,'(1A,1e16.8)') ' >>>> time step= ', & + (deltt)/tunit + + end if + + ! Save old time level + call old_save(cgen_time,ismpl) + + end if + +! ######### Forward Iteration ###### + call forward_wrapper(itimestep,ismpl) +! ################################## + + ! save and collect the computed values for: + ! - comparison with 'ddata(*,cid_pv)' (observed data) + ! - data-output (write_data.f) + call save_data(ismpl) + + if (transient) then + + ! Update simulation time + simtime(ismpl) = simtime(ismpl) + deltt + + ! wrapper for output + call write_outt(deltt,ismpl) + + ! monitoring output + if (monitor .and. flag_delt(ismpl) /= -2) then + call write_monitor(2,ismpl) + call write_monitor_user(2,ismpl) + end if + + ! Write to status_log + if ( .not. write_iter_disable) then + + ! Status log info to standard out + if (linfos(1)>=1) then + write(*,'(3A)') ' [W] : "', status_log(1:lblank(status_log)), '"' + end if + + open(76, file=status_log, status='unknown', position='append') + write(76, fmt='(I8,1e14.6,1e14.6)') itimestep, deltt, simtime(ismpl)/tunit + close(76) + + end if + + ! Check for variable time stepping divergence flag + if (flag_delt(ismpl) == -2) then + ! Restore old values of variable arrays if time step was + ! halfed (restoring simtime is handled in "deltat") + call old_restore(cgen_time, ismpl) + end if + + ! Set variable time stepping divergence flag to zero to + ! avoid double calling of deltat. + flag_delt(ismpl) = 0 + deltt = deltat(simtime(ismpl),ismpl) + + end if + + ! Important: This if statement (with the goto) needs to be + ! outside of the other "transient" scopes, to generate + ! reverse-mode code! + if (transient .and. simtime(ismpl) < simtime_end) go to 1000 +! --------------- 1000: return to next time step ---------------------- + + ! Postprocessing + ! -------------- + + ! Standard output: steady state + if (linfos(1) >= 1 .and. .not. transient) then + write(*,'(29X,1A)') ' ===> leaving nonlinear iteration' + end if + + ! Standard output: transient + if (linfos(1) >= 0 .and. transient) then + write(*,'(1A,I8,1A,1e14.6)') ' [I] : final time step = ', & + itimestep,', simulation time', simtime(ismpl)/tunit + end if + + return + + end subroutine forward_iter diff --git a/forward/forward_picard.f90 b/forward/forward_picard.f90 new file mode 100644 index 0000000..80c65f2 --- /dev/null +++ b/forward/forward_picard.f90 @@ -0,0 +1,410 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief nonlinear picard iteration for flow, heat and transport equation +!> @param[in] iter_time forward iteration counter +!> @param[in] ismpl local sample index +!> @details +!> nonlinear iteration loop (convergency) for steady state and\n +!> transient case (one time step)\n + SUBROUTINE forward_picard(iter_time,ismpl) + + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_conc + use mod_time + use mod_data + use mod_linfos + + IMPLICIT NONE + + integer :: ismpl + integer :: i + integer :: iter_nl + + ! Maximal difference and RMS-difference between old and new + ! variable array + double precision difmaxf, difrmsf + double precision difmaxt, difrmst + double precision difmaxc, difrmsc + double precision difmaxs, difrmss +! + INTEGER ijk, mode, iter_time, lblank, species + DOUBLE PRECISION neu_max, pec_max, cou_max + DOUBLE PRECISION difmaxfold, difmaxtold, difmaxcold + DOUBLE PRECISION relaxold, relaxf, relaxt, relaxc, relaxs + + ! Local non linear tolerance variables for convergence check + DOUBLE PRECISION loc_nltolf,loc_nltolt,loc_nltolc,loc_nltols +! + LOGICAL converged, lcon_sum + EXTERNAL converged, lblank + + + ! Initialisation + ! -------------- + + ! standard output + IF (linfos(3)>=2) WRITE(*,*) ' ... forward(picard)' + + ! initial values for variables + ijk = i0*j0*k0 + mode = 0 + iter_nl = 0 + + ! initialize nonlinear solver parameters: flow + loc_nltolf = nltolf +#ifdef pres_base +! convert [MPa] into [Pa] + loc_nltolf = nltolf*pa_conv +#endif + difmaxf = 1.0D9*loc_nltolf + if (linfos(3)>=2) then + WRITE(*,*) 'difmaxf = ', difmaxf + end if + relaxf = nlrelaxf + difrmsf = big + + ! initialize nonlinear solver parameters: temp + loc_nltolt = nltolt + difmaxt = 1.0D9*loc_nltolt + difrmst = big + relaxt = nlrelaxt + + ! initialize nonlinear solver parameters: conc + loc_nltolc = nltolc + difmaxc = 1.0D9*loc_nltolc + difrmsc = big + relaxc = nlrelaxc + + ! initialize nonlinear solver parameters: satn + loc_nltols = nltols + difmaxs = 1.0D9*loc_nltols + difrmss = big + relaxs = nlrelaxs + + ! init history [1] for flow + lcon(1,ismpl) = converged(difmaxf,loc_nltolf,-1,conv_hlen, & + conv_hmax,conv_history(1,1,ismpl),conv_chlen(1,ismpl), & + conv_ipos(1,ismpl)) + ! init history [2] for temperature + lcon(2,ismpl) = converged(difmaxt,loc_nltolt,-2,conv_hlen, & + conv_hmax,conv_history(1,1,ismpl),conv_chlen(1,ismpl), & + conv_ipos(1,ismpl)) + ! init history for concentration + DO i = 4, ntrans + 3 + lcon(i,ismpl) = converged(difmaxc,loc_nltolc,-i,conv_hlen, & + conv_hmax,conv_history(1,1,ismpl),conv_chlen(1,ismpl), & + conv_ipos(1,ismpl)) + END DO + + ! pre-set to enter the computation at least once + lcon_sum = .FALSE. + +! -------- begin nonlinear iteration +! ---------------------------------- +! LOOP = ITERATION lcon_sum - error !!! +! LOOP = ITERATION difmaxf,difmaxt,difmaxc - wrong !!! +!$TAF LOOP = ITERATION head,temp,conc,difmaxf,difmaxt,difmaxc + DO WHILE ( .NOT. lcon_sum .AND. iter_nl<maxiter_nl) +! -------- + + ! Preprocessing + ! ------------- + + ! loop Counter for outer nonlinear iteration + iter_nl = iter_nl + 1 + + ! save old variable arrays for checking difference later + CALL old_save(cgen_fw,ismpl) + + ! static relaxation (only flow and temperature) + IF (transient .AND. tr_switch(ismpl)) THEN + call static_relaxation(ijk,ismpl) + END IF + + ! user directory functions + CALL calc_user(ismpl) + +#ifdef head_base + ! update pressure for current head + CALL head2pres(1,ismpl) +#endif +#ifdef pres_base + ! update head from current pressure + CALL pres2head(1,ismpl) +#endif + + ! Flow equation + ! ------------- + + ! Call solver + IF (head_active .OR. pres_active) THEN +#ifdef head_base + ! head computation + CALL calc_head(ismpl) +#endif +#ifdef pres_base + ! pressure computation + CALL calc_pres(ismpl) +#endif + ELSE + lcon(1,ismpl) = .TRUE. + END IF + + ! evaluate flow + IF (head_active .OR. pres_active) THEN + + ! Neumann numbers + IF (transient .AND. tr_switch(ismpl) .AND. linfos(3)>=1) THEN +#ifdef head_base + CALL neumann_head(neu_max,ismpl) +#endif +#ifdef pres_base + CALL neumann_pres(neu_max,ismpl) +#endif +!? CALL Courant(Cou_max,ismpl) + END IF + + ! compute difference + difmaxfold = difmaxf +#ifdef head_base + if (linfos(3)>=2) then + WRITE(*,*) 'Check change with difmaxf = ', difmaxf + end if + CALL check_change(mode,pv_head,loc_nltolf,difrmsf,difmaxf,i0,j0,k0, & + head(1,1,1,ismpl),headold(1,cgen_fw,ismpl),ismpl) +#endif +#ifdef pres_base + CALL check_change(mode,pv_pres,loc_nltolf,difrmsf,difmaxf,i0,j0,k0, & + pres(1,1,1,ismpl),presold(1,cgen_fw,ismpl),ismpl) +! Include non-linear residual in error + difmaxf= ABS(difmaxf) +#endif + + ! check for convergence head/pressure + lcon(1,ismpl) = converged(difmaxf,loc_nltolf,1,conv_hlen, & + conv_hmax,conv_history(1,1,ismpl),conv_chlen(1,ismpl), & + conv_ipos(1,ismpl)) + + ! adaptive relaxation + IF (iter_nl>=2) THEN + + ! relaxation for better convergence + IF (nladapt==1) THEN + relaxold = relaxf + ! DANGER not working for saturation ! + CALL nl_relax(iter_nl,difmaxf,difmaxfold,nlmaxf,relaxf, & + relaxold,ismpl) + END IF +#ifdef head_base + ! relaxing head + CALL dscal(ijk,relaxf,head(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-relaxf,headold(1,cgen_fw,ismpl),1, & + head(1,1,1,ismpl),1) +#endif +#ifdef pres_base + ! relaxing pressure + CALL dscal(ijk,relaxf,pres(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-relaxf,presold(1,cgen_fw,ismpl),1, & + pres(1,1,1,ismpl),1) +#endif + END IF + + END IF + + ! Heat equation + ! ------------- + + ! Call solver + IF (temp_active) THEN + CALL calc_temp(ismpl) + ELSE + lcon(2,ismpl) = .TRUE. + END IF + + ! Evaluate temperature + IF (temp_active) THEN + + IF (transient .AND. tr_switch(ismpl) .AND. linfos(3)>=1) & + THEN + CALL courant(cou_max,ismpl) + CALL neumann_temp(neu_max,ismpl) + CALL peclet_temp(pec_max,ismpl) + END IF + + ! compute difference + difmaxtold = difmaxt + CALL check_change(mode,pv_temp,loc_nltolt,difrmst,difmaxt,i0,j0,k0, & + temp(1,1,1,ismpl),tempold(1,cgen_fw,ismpl),ismpl) + + ! check for convergence + lcon(2,ismpl) = converged(difmaxt,loc_nltolt,2,conv_hlen, & + conv_hmax,conv_history(1,1,ismpl),conv_chlen(1,ismpl), & + conv_ipos(1,ismpl)) + + ! adaptive relaxation + IF (iter_nl>=2) THEN + ! relaxation for better convergence + IF (nladapt==1) THEN + relaxold = relaxt + CALL nl_relax(iter_nl,difmaxt,difmaxtold,nlmaxt,relaxt, & + relaxold,ismpl) + END IF + CALL dscal(ijk,relaxt,temp(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-relaxt,tempold(1,cgen_fw,ismpl),1, & + temp(1,1,1,ismpl),1) + END IF + + END IF + + ! Open spot for future implementation of another equation at + ! lcon(3,ismpl) + lcon(3,ismpl) = .TRUE. + + ! Transport equation + ! ------------- + + IF (trac_active) THEN + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_conc (tracer)' + END IF + DO species = 1, ntrac + + ! Call solver + IF (trac_active) THEN + CALL calc_conc(species,ismpl) + ELSE + lcon(3+species,ismpl) = .TRUE. + END IF + + ! evaluate concentration + IF (trac_active) THEN + + IF (transient .AND. tr_switch(ismpl) .AND. & + linfos(3)>=1 .AND. species==1) THEN + CALL courant(cou_max,ismpl) + CALL neumann_conc(neu_max,ismpl) + CALL peclet_conc(pec_max,ismpl) + END IF + + ! compute difference + difmaxcold = difmaxc + + ! Check change + CALL check_change(mode,pv_conc,loc_nltolc,difrmsc,difmaxc,i0,j0,k0, & + conc(1,1,1,species,ismpl),concold(1,species,cgen_fw, & + ismpl),ismpl) + + ! check for convergence + lcon(3+species,ismpl) = converged(difmaxc,loc_nltolc, & + 3+species,conv_hlen,conv_hmax,conv_history(1,1,ismpl), & + conv_chlen(1,ismpl),conv_ipos(1,ismpl)) + + ! adaptive relaxation + IF (iter_nl>=2) THEN + ! relaxation for better convergence + IF (nladapt==1) THEN + relaxold = relaxc + CALL nl_relax(iter_nl,difmaxc,difmaxcold,nlmaxc, & + relaxc,relaxold,ismpl) + END IF + CALL dscal(ijk,relaxc,conc(1,1,1,species,ismpl),1) + CALL daxpy(ijk,1.0D0-relaxc,concold(1,species,cgen_fw, & + ismpl),1,conc(1,1,1,species,ismpl),1) + END IF + + conc_conv(species,ismpl) = difmaxc + + END IF + + END DO + + ! Postprocessing + ! ------------- + +! check whether pres/temp/(conc) in domain of props validity + CALL check_domain(ismpl) + +! summarise all convergency criteria + lcon_sum = .TRUE. + DO i = 1, conv_hmax + IF ( .NOT. lcon(i,ismpl)) lcon_sum = .FALSE. + END DO + + ! generate convergency output + IF (linfos(3)>=1) THEN +#ifdef head_base + WRITE(*,'(1A,1I6,2(1A,1e16.8))') ' [I] : iter_nl =', iter_nl, & + ', difmaxh =', difmaxf, ', difmaxt =', difmaxt +#endif +#ifdef pres_base + WRITE(*,'(1A,1I6,2(1A,1e16.8))') ' [I] : iter_nl =', iter_nl, & + ', difmaxp =', difmaxf*Pa_conv1, ', difmaxt =', difmaxt, & + ', difmaxs =', difmaxs +#endif + IF (ntrac>=1) WRITE(*,'(1A,99e16.8)') ' difmaxc[*] =', (conc_conv(i,ismpl),i=1,ntrac) + END IF + IF ((runmode>=-1) .AND. ( .NOT. write_iter_disable)) THEN + IF (linfos(3)>=2) WRITE(*,'(3A)') ' [W] : "', status_log(1:lblank(status_log)), '"' + OPEN(76,file=status_log,status='unknown',position='append') +#ifdef head_base + WRITE(76,'(I11,99e16.8)') iter_nl, difmaxf, difmaxt,(conc_conv(i,ismpl),i=1,ntrac) +#endif +#ifdef pres_base + WRITE(76,'(I11,99e16.8)') iter_nl, difmaxf*Pa_conv1, difmaxt, difmaxs, (conc_conv(i,ismpl),i=1,ntrac) +#endif + CLOSE(76) + END IF + + ! calculate total salinity (used only in property module + ! basc) + CALL set_tsal(ismpl) + +#ifdef DEBUG + DO i = 1, n_debugout + IF (debugout(1,i)==iter_time .AND. debugout(2,i)==iter_nl) THEN + WRITE(project_sfx(ismpl),'(1A1,1I5.5,1A1,1I3.3)') '_', iter_time, 'x', iter_nl + CALL write_tecdiff(-2,ismpl) + project_sfx(ismpl) = ' ' + END IF + END DO +#endif + +! -------- + END DO +! -------- end nonlinear iteration +! -------------------------------- + + ! Variable time step + call set_var_deltat(iter_nl, ismpl) + + ! Standard output + IF (transient .AND. tr_switch(ismpl)) THEN + IF (linfos(3)>=2) WRITE(*,'(1A,1I10,1A)') 'timestep ', iter_time, ', leaving nonlinear iteration' + END IF + + RETURN + + END SUBROUTINE forward_picard diff --git a/forward/forward_preparation.f90 b/forward/forward_preparation.f90 new file mode 100644 index 0000000..5c4a291 --- /dev/null +++ b/forward/forward_preparation.f90 @@ -0,0 +1,70 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper for preparation of forward run, mostly input +!> @param[in] filename input filename as read from shemade.job +!> @param[inout] ismpl local sample index +!> @details +!> This input wrapper calls the read-in routines and initializes +!> first output to the status log and the command line. +subroutine forward_preparation(filename, ismpl) + + use mod_genrl, only: runmode + use mod_genrlc, only: filename_data +#ifndef noHDF + use mod_input_file_parser_hdf5, only: h5parse_open_datafile, & + h5parse_close_datafile +#endif + + implicit none + + integer :: ismpl + + character (len=80), intent (in) :: filename + + integer, external :: lblank + logical, external :: test_option + +#ifndef noHDF + CALL h5parse_open_datafile(filename) +#endif + + ! read forward model + CALL read_model(filename,ismpl) + CALL read_control(filename,ismpl) + ! only forward propcessing =<1 + runmode = min(runmode,1) + ! read timestep parameter + CALL read_time(filename,ismpl) + ! read data + IF (runmode>0) CALL read_data(filename_data,ismpl) + ! split units + CALL read_split(filename,ismpl) + + ! First status log output + call write_status_log(filename, ismpl) + +#ifndef noHDF + CALL h5parse_close_datafile() +#endif + +end subroutine forward_preparation diff --git a/forward/forward_wrapper.f90 b/forward/forward_wrapper.f90 new file mode 100644 index 0000000..ae084df --- /dev/null +++ b/forward/forward_wrapper.f90 @@ -0,0 +1,43 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper for the forward simulation call +!> @param[in] iter time iteration counter +!> @param[in] ismpl local sample index +!> @details +!> Seperates the equation system solving from the specific nonlinear +!> solver (Picard based)\n + subroutine forward_wrapper(iter,ismpl) + + implicit none + + integer :: ismpl + + integer, intent (in) :: iter + +! ######### Forward Iteration ###### + call forward_picard(iter,ismpl) +! ################################## + + return + + end subroutine forward_wrapper diff --git a/forward/forward_write.f90 b/forward/forward_write.f90 new file mode 100644 index 0000000..f0967ab --- /dev/null +++ b/forward/forward_write.f90 @@ -0,0 +1,38 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper routine for common write output +!> @param[in] i index/iteration number +!> @param[in] ismpl local sample index + SUBROUTINE forward_write(i,ismpl) + IMPLICIT NONE + INTEGER i, ismpl +! + CALL write_hdf(i,ismpl) + CALL write_tecplot(i,ismpl) + CALL write_tecplotc(i,ismpl) + CALL write_vtk(i,ismpl) + CALL write_text(i,ismpl) + CALL write_user(i,ismpl) + CALL write_logs(i,ismpl) + RETURN + END diff --git a/forward/get_tpbcalbe.f90 b/forward/get_tpbcalbe.f90 new file mode 100644 index 0000000..6c91bb3 --- /dev/null +++ b/forward/get_tpbcalbe.f90 @@ -0,0 +1,73 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief time depended boundary condition modificators +!> @param[out] malfa alfa modificator +!> @param[out] mbeta beta modificator +!> @param[in] tpbcu time period BC table index +!> @param[in] ismpl local sample index +!> @details +!> "GET Time Periods Boundary Condition ALfa & BEta"\n +!> get the alfa and beta modificators for time dependend bc-values\n + SUBROUTINE get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) + use arrays + use mod_genrl + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: k + + INTEGER tpbcu, imt + DOUBLE PRECISION malfa, mbeta, mtime + INTRINSIC abs + +! default - when not time depended + malfa = 0.0D0 + mbeta = 1.0D0 +! + IF (tpbcu>0) THEN + k = 0 + imt = 0 +! next bc-tp entry +100 imt = imt + 1 + mtime = bcperiod(imt,1,tpbcu,ismpl) + IF (mtime<=simtime(ismpl)) THEN + malfa = bcperiod(imt,2,tpbcu,ismpl) + mbeta = bcperiod(imt,3,tpbcu,ismpl) +! save index of the valid start time + k = imt + END IF +! +! !!! this IF statement (with the GOTO) needs to be outside of the +! other "mtime<=simtime(ismpl)" scopes, to generate reverse-mode code !!! + IF (mtime<=simtime(ismpl).AND.imt<ibcperiod(tpbcu)) GO TO 100 + IF (k>0) THEN + IF ( .NOT. lbcperiod(k,tpbcu)) THEN +! disable this BC (switched off) + tpbcu = -abs(tpbcu) + END IF + END IF + END IF +! + RETURN + END diff --git a/forward/head/calc_head.f90 b/forward/head/calc_head.f90 new file mode 100644 index 0000000..fdd5ba6 --- /dev/null +++ b/forward/head/calc_head.f90 @@ -0,0 +1,95 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief top level routine for setup aand computing head flow +!> @param[in] ismpl local sample index + SUBROUTINE calc_head(ismpl) + use arrays + use mod_genrlc + use mod_genrl + use mod_flow + use mod_time + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i + INCLUDE 'OMP_TOOLS.inc' + INTEGER ijk + + + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_head' +! +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + + ijk = i0*j0*k0 + + ! default to mark a non-boundary +!$OMP master + DO i = 1, ijk + bc_mask(i,ismpl) = '+' + END DO +!$OMP end master + + ! initialize coefficients for sparse solvers as zero + CALL omp_set_dval(ijk,0.D0,a(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,b(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,c(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,d(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,e(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,f(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,g(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,w(1,1,1,ismpl)) + +!$OMP barrier + + ! calculate coefficients + CALL set_hcoef(ismpl) + + ! set fluid sources/sinks (currently hardcoded to zero) + CALL set_hq(ismpl) + +!$OMP barrier + + ! calculate coefficients for right hand side + CALL set_hcoefrs(ismpl) + +#ifdef fOMP +!$OMP end parallel +#endif + + ! set boundary conditions + CALL set_hbc(ismpl) + + ! standard output + IF (linfos(3)>=2) WRITE(*,*) ' ... solve(head)' + + ! solve head + CALL solve(pv_head,-1,head(1,1,1,ismpl),errf,aparf,controlf, & + ismpl) + + RETURN + + END diff --git a/forward/head/hbuoy.f90 b/forward/head/hbuoy.f90 new file mode 100644 index 0000000..5414941 --- /dev/null +++ b/forward/head/hbuoy.f90 @@ -0,0 +1,58 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate buoyancy for head equation +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return buoyancy +!> @details +!>calculate buoyancy for head equation\n +!>sign convention: negative for positive buoyancy\n + DOUBLE PRECISION FUNCTION buoy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION rhor, rhav, hh, h0, h1, prod, summ + DOUBLE PRECISION rhof, kz, visf + EXTERNAL rhof, kz, visf + + rhav = 0.5D0*(rhof(i,j,k+1,ismpl)+rhof(i,j,k,ismpl)) + rhor = (rhav-rref)/rref + + hh = 0.D0 + h0 = kz(i,j,k,ismpl)*rhof(i,j,k,ismpl)*grav/visf(i,j,k,ismpl) + h1 = kz(i,j,k+1,ismpl)*rhof(i,j,k+1,ismpl)*grav/ & + visf(i,j,k+1,ismpl) + summ = h0 + h1 + prod = h0*h1 + IF (summ>0.D0) hh = 2.0D0*prod/summ + + buoy = hh*rhor + + RETURN + END diff --git a/forward/head/head2pres.f90 b/forward/head/head2pres.f90 new file mode 100644 index 0000000..b8c1bff --- /dev/null +++ b/forward/head/head2pres.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute pressure from head +!> @param[in] init flag: 0-init, 1-normal setup +!> @param[in] ismpl local sample index +!> @details +!> parallelisation wrapper for pressure computation + SUBROUTINE head2pres(init,ismpl) + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + INTEGER init + + IF (linfos(3)>=2) WRITE(*,'(A,I1,A)') & + ' ... pressure (init=', init, ')' +! +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif +! + CALL omp_head2pres(init,ismpl) +! +#ifdef fOMP +!$OMP end parallel +#endif +! + RETURN + END diff --git a/forward/head/hfluxes.f90 b/forward/head/hfluxes.f90 new file mode 100644 index 0000000..d784db6 --- /dev/null +++ b/forward/head/hfluxes.f90 @@ -0,0 +1,328 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x velocity (m/s) + DOUBLE PRECISION FUNCTION vx(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION dif, ti + EXTERNAL ti + + vx = 0.D0 + if (.not. head_active .and. vdefaultswitch) then + vx = vdefault(1,ismpl) + end if + IF (i0>1 .AND. i<i0 .AND. head_active) THEN +#ifdef head_base + dif = head(i+1,j,k,ismpl) - head(i,j,k,ismpl) + vx = -ti(i,j,k,ismpl)*dif +#endif + END IF + RETURN + END + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y velocity (m/s) + DOUBLE PRECISION FUNCTION vy(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION dif, tj + EXTERNAL tj + + vy = 0.D0 + if (.not. head_active .and. vdefaultswitch) then + vy = vdefault(2,ismpl) + end if + IF (j0>1 .AND. j<j0 .AND. head_active) THEN +#ifdef head_base + dif = head(i,j+1,k,ismpl) - head(i,j,k,ismpl) + vy = -tj(i,j,k,ismpl)*dif +#endif + END IF + RETURN + END + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z velocity (m/s) + DOUBLE PRECISION FUNCTION vz(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION dif, tk, buoy + EXTERNAL tk, buoy + + vz = 0.D0 + if (.not. head_active .and. vdefaultswitch) then + vz = vdefault(3,ismpl) + end if + IF (k0>1 .AND. k<k0 .AND. head_active) THEN +#ifdef head_base + dif = head(i,j,k+1,ismpl) - head(i,j,k,ismpl) + vz = -tk(i,j,k,ismpl)*dif - buoy(i,j,k,ismpl) +#endif + END IF + RETURN + END + +!> @brief calculate velocities at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x velocity (m/s) + DOUBLE PRECISION FUNCTION vxc(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION vx, amean + EXTERNAL vx, amean + + vxc = 0.D0 + IF (i0<=1 .OR. .NOT.head_active) RETURN +#ifdef head_base + IF (i>1 .AND. i<i0) THEN + vxc = amean(vx(i,j,k,ismpl),vx(i-1,j,k,ismpl)) + ELSE IF (i==1) THEN + vxc = vx(i,j,k,ismpl) + ELSE IF (i==i0) THEN + vxc = vx(i-1,j,k,ismpl) + END IF +#endif + RETURN + END + +!> @brief calculate y-velocities at cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y velocity (m/s) + DOUBLE PRECISION FUNCTION vyc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION vy, amean + EXTERNAL vy, amean + + vyc = 0.D0 + IF (j0<=1 .OR. .NOT.head_active) RETURN +#ifdef head_base + IF (j>1 .AND. j<j0) THEN + vyc = amean(vy(i,j,k,ismpl),vy(i,j-1,k,ismpl)) + ELSE IF (j==1) THEN + vyc = vy(i,j,k,ismpl) + ELSE IF (j==j0) THEN + vyc = vy(i,j-1,k,ismpl) + END IF +#endif + RETURN + END + +!> @brief calculate z-velocities at cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z velocity (m/s) + DOUBLE PRECISION FUNCTION vzc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION vz, amean + EXTERNAL vz, amean + + vzc = 0.D0 + IF (k0<=1 .OR. .NOT.head_active) RETURN +#ifdef head_base + IF (k>1 .AND. k<k0) THEN + vzc = amean(vz(i,j,k,ismpl),vz(i,j,k-1,ismpl)) + ELSE IF (k==1) THEN + vzc = vz(i,j,k,ismpl) + ELSE IF (k==k0) THEN + vzc = vz(i,j,k-1,ismpl) + END IF +#endif + RETURN + END + +!> @brief harmonic mean Kx on cell faces in x direction over delx* +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x hydraulic conductivity over delx* (1/s) +!> @details +!> Compute the harmonic mean of Kx on the cell face in positive +!> x-direction from the current node (i, j, k) divided by the +!> x-distance of the current node (i, j, k) to the neighboring node +!> (i+1, j, k). +!> +!> delx* = 0.5 ( delx(i) + delx(i+1) ) +!> +!> Kx / delx* = [ 0.5*delx(i+1)/K(i+1) + 0.5*delx(i)/K(i) ]**-1 +!> +!> = [ ( 0.5* K(i)* delx(i+1) + 0.5*K(i+1)* delx(i) ) / ( K(i)*K(i+1) ) ]**-1 +!> +!> = [ ( 0.5 * summ ) / (prod) ]**-1 = 2.0*prod/summ + DOUBLE PRECISION FUNCTION ti(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kx, rhof, visf + EXTERNAL kx, rhof, visf + + ti = 0.D0 + IF (i0>1 .AND. i<i0) THEN + f1 = kx(i,j,k,ismpl)*rhof(i,j,k,ismpl)*grav/ & + visf(i,j,k,ismpl) + f2 = kx(i+1,j,k,ismpl)*rhof(i+1,j,k,ismpl)*grav/ & + visf(i+1,j,k,ismpl) + prod = f1*f2 + summ = f1*delx(i+1) + f2*delx(i) + IF (summ>0.D0) ti = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief harmonic mean Ky on cell faces in y direction over dely* +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y hydraulic conductivity over dely* (1/s) +!> @details +!> Compute the harmonic mean of Ky on the cell face in positive +!> y-direction from the current node (i, j, k) divided by the +!> y-distance of the current node (i, j, k) to the neighboring node +!> (i, j+1, k). +!> +!> dely* = 0.5 ( dely(j) + dely(j+1) ) +!> +!> Ky / dely* = [ 0.5*dely(j+1)/K(j+1) + 0.5*dely(j)/K(j) ]**-1 +!> +!> = [ ( 0.5* K(j)* dely(j+1) + 0.5*K(j+1)* dely(j) ) / ( K(j)*K(j+1) ) ]**-1 +!> +!> = [ ( 0.5 * summ ) / (prod) ]**-1 = 2.0*prod/summ + DOUBLE PRECISION FUNCTION tj(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, ky, rhof, visf + EXTERNAL ky, rhof, visf + + tj = 0.D0 + IF (j0>1 .AND. j<j0) THEN + f1 = ky(i,j,k,ismpl)*rhof(i,j,k,ismpl)*grav/ & + visf(i,j,k,ismpl) + f2 = ky(i,j+1,k,ismpl)*rhof(i,j+1,k,ismpl)*grav/ & + visf(i,j+1,k,ismpl) + prod = f1*f2 + summ = f1*dely(j+1) + f2*dely(j) + IF (summ>0.D0) tj = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief harmonic mean Kz on cell faces in z direction over delz* +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z hydraulic conductivity over delz* (1/s) +!> @details +!> Compute the harmonic mean of Kz on the cell face in positive +!> z-direction from the current node (i, j, k) divided by the +!> z-distance of the current node (i, j, k) to the neighboring node +!> (i, j, k+1). +!> +!> delz* = 0.5 ( delz(k) + delz(k+1) ) +!> +!> Kz / delz* = [ 0.5*delz(k+1)/K(k+1) + 0.5*delz(k)/K(k) ]**-1 +!> +!> = [ ( 0.5* K(k)* delz(k+1) + 0.5*K(k+1)* delz(k) ) / ( K(k)*K(k+1) ) ]**-1 +!> +!> = [ ( 0.5 * summ ) / (prod) ]**-1 = 2.0*prod/summ + DOUBLE PRECISION FUNCTION tk(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kz, rhof, visf + EXTERNAL kz, rhof, visf + + tk = 0.D0 + IF (k0>1 .AND. k<k0) THEN + f1 = kz(i,j,k,ismpl)*rhof(i,j,k,ismpl)*grav/ & + visf(i,j,k,ismpl) + f2 = kz(i,j,k+1,ismpl)*rhof(i,j,k+1,ismpl)*grav/ & + visf(i,j,k+1,ismpl) + prod = f1*f2 + summ = f1*delz(k+1) + f2*delz(k) + IF (summ>0.D0) tk = 2.D0*prod/summ + END IF + RETURN + END diff --git a/forward/head/hstor.f90 b/forward/head/hstor.f90 new file mode 100644 index 0000000..ee498a5 --- /dev/null +++ b/forward/head/hstor.f90 @@ -0,0 +1,44 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates the bulk storativity +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return bulk storativity +!> @details +!> storb(i,j,k,ismpl) calculates the bulk storativity \n +!> at node(i,j,k).\n + DOUBLE PRECISION FUNCTION hstor(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION rhof, compm, compf, por + EXTERNAL rhof, compm, compf, por + + hstor = grav*rhof(i,j,k,ismpl)*(compm(i,j,k,ismpl)+por(i,j,k, & + ismpl)*compf(i,j,k,ismpl)) + RETURN + END diff --git a/forward/head/neumann_head.f90 b/forward/head/neumann_head.f90 new file mode 100644 index 0000000..e651cbe --- /dev/null +++ b/forward/head/neumann_head.f90 @@ -0,0 +1,214 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_neumann_head" +!> @param[out] neumann_max neumann criteria +!> @param[in] ismpl local sample index + SUBROUTINE neumann_head(neumann_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION neumann_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_neumann_head(neumann_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate grid neuman numbers (head) +!> @param[out] neumann_max maximal neuman number +!> @param[in] ismpl local sample index + SUBROUTINE omp_neumann_head(neumann_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + INTEGER c1, c2, c3 + DOUBLE PRECISION neumann_maxx + DOUBLE PRECISION neumann_minx + DOUBLE PRECISION neumann_avgx + DOUBLE PRECISION neumann_maxy + DOUBLE PRECISION neumann_miny + DOUBLE PRECISION neumann_avgy + DOUBLE PRECISION neumann_maxz + DOUBLE PRECISION neumann_minz + DOUBLE PRECISION neumann_avgz + ! DOUBLE PRECISION neumann_x + ! DOUBLE PRECISION neumann_y + ! DOUBLE PRECISION neumann_z + DOUBLE PRECISION val + DOUBLE PRECISION neumann_max + DOUBLE PRECISION delt + DOUBLE PRECISION fac + DOUBLE PRECISION davg + DOUBLE PRECISION deltat + EXTERNAL deltat + DOUBLE PRECISION ti, tj, tk, rhof, visf, por, compf, compm, & + hstor + EXTERNAL ti, tj, tk, rhof, visf, por, compf, compm, hstor + + + delt = deltat(simtime(ismpl),ismpl) + + IF ( .NOT. (transient .AND. tr_switch(ismpl))) THEN +!$OMP master + WRITE(*,*) ' neumann-head: not defined for steady state' +!$OMP end master + RETURN + ELSE IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... neumann-head: delt/tunit = ', & + delt/tunit + WRITE(*,*) +!$OMP end master + END IF + +! val in x + c1 = 0 + neumann_maxx = small + neumann_minx = big + neumann_avgx = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + fac = delt/hstor(i,j,k,ismpl) + val = fac*ti(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxx) neumann_maxx = val + IF (val<neumann_minx) neumann_minx = val + neumann_avgx = neumann_avgx + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in y + c2 = 0 + neumann_maxy = small + neumann_miny = big + neumann_avgy = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + fac = delt/hstor(i,j,k,ismpl) + val = fac*tj(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxy) neumann_maxy = val + IF (val<neumann_miny) neumann_miny = val + neumann_avgy = neumann_avgy + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in z + c3 = 0 + neumann_maxz = small + neumann_minz = big + neumann_avgz = 0.0D0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + fac = delt/hstor(i,j,k,ismpl) + val = fac*tk(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxz) neumann_maxz = val + IF (val<neumann_minz) neumann_minz = val + neumann_avgz = neumann_avgz + val + END DO + END DO + END DO +!$OMP end do nowait + +! compute global sum for all values + CALL omp_summe(neumann_maxx,neumann_minx,neumann_avgx, & + neumann_maxy,neumann_miny,neumann_avgy,neumann_maxz, & + neumann_minz,neumann_avgz,c1,c2,c3,ismpl) + +!$OMP master + IF (i0>2) THEN + neumann_avgx = neumann_avgx/dble(c1) + ELSE + neumann_maxx = 0.0D0 + neumann_minx = 0.0D0 + neumann_avgx = 0.0D0 + END IF + IF (j0>2) THEN + neumann_avgy = neumann_avgy/dble(c2) + ELSE + neumann_maxy = 0.0D0 + neumann_miny = 0.0D0 + neumann_avgy = 0.0D0 + END IF + IF (k0>2) THEN + neumann_avgz = neumann_avgz/dble(c3) + ELSE + neumann_maxz = 0.0D0 + neumann_minz = 0.0D0 + neumann_avgz = 0.0D0 + END IF + + neumann_max = max(neumann_maxx,neumann_maxy,neumann_maxz) + + IF (linfos(3)>=2) THEN + WRITE(*,*) 'neumann number for head in x,y,z:' + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' max. : ', & + neumann_maxx, ', ', neumann_maxy, ', ', neumann_maxz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' min. : ', & + neumann_minx, ', ', neumann_miny, ', ', neumann_minz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + neumann_avgx, ', ', neumann_avgy, ', ', neumann_avgz + END IF + + IF (linfos(3)>=1 .AND. neumann_max>0.5D0) THEN + WRITE(*,'(a)') '!!!: neumann head greater than 1/2 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + neumann_maxx, 'y: ', neumann_maxy, 'z: ', neumann_maxz + WRITE(*,*) + END IF +!$OMP end master + + RETURN + END diff --git a/forward/head/omp_head2pres.f90 b/forward/head/omp_head2pres.f90 new file mode 100644 index 0000000..8bd3428 --- /dev/null +++ b/forward/head/omp_head2pres.f90 @@ -0,0 +1,83 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief pressure in Pa from hydraulic potential und heigth above hz=0.0d0 +!> @param[in] init flag: 0-init, 1-normal setup +!> @param[in] ismpl local sample index +!> @details +!> pressure in MPa from hydraulic potential und height above hz=0.0 \n +!> p(surface) = 0.1 MPa \n +!> OUTPUT in Pa\n + SUBROUTINE omp_head2pres(init,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + INTEGER init + DOUBLE PRECISION psurf + DOUBLE PRECISION dif + DOUBLE PRECISION zero + PARAMETER (zero=0.0D0) + + +! presetting for dirichlet boundary conditions to avoid site effects + CALL set_dhbc(ismpl) + CALL set_dtbc(ismpl) +!$OMP barrier +! + psurf = 1.0D5 +! + IF (init==0) THEN +! initialize +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + dif = head(i,j,k,ismpl) - delza(k) + pres(i,j,k,ismpl) = psurf + IF (dif>zero) pres(i,j,k,ismpl) = psurf + dif*rref*grav + END DO + END DO + END DO +!$OMP end do nowait + ELSE +! pres and temp have already appropriate values +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + dif = head(i,j,k,ismpl) - delza(k) + pres(i,j,k,ismpl) = psurf +! jbr: pres = (h-z)*rref*grav + IF (dif>zero) pres(i,j,k,ismpl) = psurf + & + rref*dif*grav + END DO + END DO + END DO +!$OMP end do nowait + END IF +! + RETURN + END diff --git a/forward/head/set_hbc.f90 b/forward/head/set_hbc.f90 new file mode 100644 index 0000000..c57a34a --- /dev/null +++ b/forward/head/set_hbc.f90 @@ -0,0 +1,193 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the head equation according to the boundary conditions +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the head equation according to the boundary conditions,\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_hbc(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype, i_dir + DOUBLE PRECISION val, malfa, mbeta + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +!aw i_dir = ibc_data(ib,cbc_dir) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*val +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = val + head(i,j,k,ismpl) = val +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! neumann nodes - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) + i_dir = ibc_data(ib,cbc_dir) +! "neumann"?, skip otherwise + IF (bctype==bt_neum.OR.bctype==bt_neuw) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN + IF ((i_dir==0)) val = val/(delx(i)*dely(j)*delz(k)) + IF ((i_dir==1) .OR. (i_dir==2)) val = val/delx(i) + IF ((i_dir==3) .OR. (i_dir==4)) val = val/dely(j) + IF ((i_dir==5) .OR. (i_dir==6)) val = val/delz(k) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - val + END IF + END IF + END DO + + RETURN + END + +!> @brief modify HEAD for the head equation according to the boundary conditions +!> @param[in] ismpl local sample index +!> @details +!> modify HEAD for the head equation according to the boundary conditions\n + SUBROUTINE set_dhbc(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype + DOUBLE PRECISION val, malfa, mbeta + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + +!$OMP do schedule(static) + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) head(i,j,k,ismpl) = val + END IF + END DO +!$OMP end do nowait +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + RETURN + END diff --git a/forward/head/set_hcoef.f90 b/forward/head/set_hcoef.f90 new file mode 100644 index 0000000..11f1625 --- /dev/null +++ b/forward/head/set_hcoef.f90 @@ -0,0 +1,168 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate coefficents for the head equation +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the head equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_hcoef(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + DOUBLE PRECISION ti, tj, tk + EXTERNAL ti, tj, tk + + +!$OMP master + IF (linfos(3)>=2) WRITE(*,*) ' ... fcoef' +!$OMP end master + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + + IF (i0>1) THEN + IF (i<i0) THEN + e(i,j,k,ismpl) = ti(i,j,k,ismpl)/delx(i) + END IF + IF (i>1) THEN + c(i,j,k,ismpl) = ti(i-1,j,k,ismpl)/delx(i) + END IF + END IF + + IF (j0>1) THEN + IF (j<j0) THEN + f(i,j,k,ismpl) = tj(i,j,k,ismpl)/dely(j) + END IF + IF (j>1) THEN + b(i,j,k,ismpl) = tj(i,j-1,k,ismpl)/dely(j) + END IF + END IF + + IF (k0>1) THEN + IF (k<k0) THEN + g(i,j,k,ismpl) = tk(i,j,k,ismpl)/delz(k) + END IF + IF (k>1) THEN + a(i,j,k,ismpl) = tk(i,j,k-1,ismpl)/delz(k) + END IF + END IF + + d(i,j,k,ismpl) = -(e(i,j,k,ismpl)+c(i,j,k,ismpl)+f(i,j,k & + ,ismpl)+b(i,j,k,ismpl)+g(i,j,k,ismpl)+a(i,j,k,ismpl)) + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END + +!> @brief calculate right hand side for the head equation +!> @param[in] ismpl local sample index +!> @details +!> calculate right hand side for the head equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_hcoefrs(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + DOUBLE PRECISION src, deltf, sijk + ! INTEGER c1, c2, c3, c4 + + DOUBLE PRECISION buoy, compf, compm, rhof, por, deltat, hstor, & + visf + EXTERNAL buoy, compf, compm, rhof, por, deltat, hstor, visf + + + deltf = deltat(simtime(ismpl),ismpl) + +! rhs: sources + + IF (transient .AND. tr_switch(ismpl)) THEN +! - - - - - - - - transient - - - - - - - - - - - + CALL omp_mvp(i0,j0,k0,headold(1,cgen_time,ismpl), & + x(1,1,1,ismpl),a(1,1,1,ismpl),b(1,1,1,ismpl), & + c(1,1,1,ismpl),d(1,1,1,ismpl),e(1,1,1,ismpl), & + f(1,1,1,ismpl),g(1,1,1,ismpl)) + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + src = 0.0D0 +! buoyancy + IF (k<k0) src = src + buoy(i,j,k,ismpl)/delz(k) + IF (k>1) src = src - buoy(i,j,k-1,ismpl)/delz(k) + + sijk = hstor(i,j,k,ismpl) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - sijk/(deltf*thetaf) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + (1.0D0-thetaf)*x(i,j,k,ismpl) - & + sijk*headold(i+(j-1)*i0+(k-1)*i0*j0,cgen_time,ismpl) & + /deltf - src + w(i,j,k,ismpl) = w(i,j,k,ismpl)/thetaf + END DO + END DO + END DO +!$OMP end do nowait + + ELSE +! - - - - - - - - steady state - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + src = 0.0D0 +! buoyancy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + IF (k<k0) src = src + buoy(i,j,k,ismpl)/delz(k) + IF (k>1) src = src - buoy(i,j,k-1,ismpl)/delz(k) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - src + END DO + END DO + END DO +!$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/head/set_hq.f90 b/forward/head/set_hq.f90 new file mode 100644 index 0000000..592e8ff --- /dev/null +++ b/forward/head/set_hq.f90 @@ -0,0 +1,64 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the head equation according to the prescribed sources and sinks +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the head equation according to the prescribed sources and sinks\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_hq(ismpl) + use arrays + use mod_genrl + use mod_time + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION deltat, deltf, qf + EXTERNAL deltat, qf + +! rhs: sources + IF (transient .AND. tr_switch(ismpl)) THEN + deltf = deltat(simtime(ismpl),ismpl) +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qf(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + ELSE +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qf(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/input/calc_deltatime.f90 b/forward/input/calc_deltatime.f90 new file mode 100644 index 0000000..16baeb7 --- /dev/null +++ b/forward/input/calc_deltatime.f90 @@ -0,0 +1,152 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute time steps table delta_time +!> @param[in] ismpl local sample index +!> @details +!> Compute the time steps table delta time. \n\n +!> +!> Linear: dt(j) = (tend-tstart)/n \n\n +!> +!> Logarithmic: dt(j) = tunit * (10**(j/n*((tstart-tend)/tunit + 1)) - +!> 1) \n\n +!> +!> Varied logarithmic (tstart needs to be non-zero): dt(j) = tstart * +!> (10**(j/n * tend/tstart) - 10**((j-1)/n * tend/tstart)) \n\n +!> +!> Logarithmic decreasing: dt(j) = tunit * +!> (10**((n-j)/n*((tstart-tend)/tunit + 1)) - 1) \n\n +subroutine calc_deltatime(ismpl) + + use arrays, only: delta_time + use mod_genrl, only: memory + use mod_time, only: nperiod, ntimestep, tunit, iperiod, dperiod + + implicit none + + ! local sample index + integer :: ismpl + + ! Counter: overall time step + integer :: it + + ! Number of time steps in current time periods + integer :: nstep + + ! Counters: Period, time step of current period + integer :: iper, istep + + ! Logarithmic factor, used in logarithmic time stepping + double precision :: facl + + ! End (t1) and start (t0) time of time step + double precision :: t1, t0 + + + ! Re-allocate delta_time to total number of time periods + deallocate(delta_time) + memory = memory - 1 + allocate(delta_time(ntimestep)) + memory = memory + ntimestep + + ! Set intitial time period counter + it = 0 + + ! Loop over time periods + do iper = 1, nperiod + + ! Number of time steps in current time periods + nstep = iperiod(iper,1) + + ! Compute time steps according to type + if (iperiod(iper,2) == 1) then + ! type: linear + + do istep = 1, nstep + it = it + 1 + delta_time(it) = (dperiod(iper,2) - dperiod(iper,1)) / dble(nstep) + end do + + else if (iperiod(iper,2) == 2) then + ! type: logarithmically increasing + + facl = log10((dperiod(iper,2) - dperiod(iper,1))/tunit + 1.D0) / dble(nstep) + + t0 = dperiod(iper,1) + do istep = 1, nstep + it = it + 1 + t1 = dperiod(iper,1) + tunit * 10.0d0**(dble(istep) * facl) - tunit + delta_time(it) = t1 - t0 + t0 = t1 + end do + + else if (iperiod(iper,2)==3) then + ! type: varied logarithmically increasing + + if (dperiod(iper,1) <= 0.0d0) then + write(unit = *, fmt = *) 'error (read_time.f90): ',& + 'No varied Log with starting time 0.0d0' + stop 1 + end if + + facl = log10(dperiod(iper,2) / dperiod(iper,1)) / dble(nstep) + + t0 = dperiod(iper,1) + do istep = 1, nstep + it = it + 1 + t1 = dperiod(iper,1) * 10.0d0**(dble(istep) * facl) + delta_time(it) = t1 - t0 + t0 = t1 + end do + + else if (iperiod(iper,2)==-2) then + ! type: logarithmically decreasing + + facl = log10((dperiod(iper,2) - dperiod(iper,1))/tunit + 1.0d0) / dble(nstep) + + t0 = dperiod(iper,2) + do istep = nstep - 1, 0, -1 + it = it + 1 + t1 = dperiod(iper,1) + tunit * 10.0d0**(dble(istep) * facl) - tunit + delta_time(it) = t0 - t1 + t0 = t1 + end do + + else + write(*,'(1A,1I2,1A,1I2,1A)') & + 'error: wrong time step type ', iperiod(iper,2), ' at ', iper, & + ' in "read_time.f" !' + stop + + end if + + end do + + ! Sanity check: Total number of time steps + if (it /= ntimestep) then + write(*,'(1A)') 'error: lost some time steps in "read_time.f" !' + stop + end if + + return + +end subroutine calc_deltatime diff --git a/forward/input/read_array.f90 b/forward/input/read_array.f90 new file mode 100644 index 0000000..9ee6d8b --- /dev/null +++ b/forward/input/read_array.f90 @@ -0,0 +1,87 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read MM*NN double precision values from file +!> @param[in] fid file id +!> @param[out] AA array to fill +!> @param[in] MM number of values expected in each line +!> @param[in] NN number of lines +!> @param[in] ustr section name +!> @param[in] ismpl local sample index (ignored here) + SUBROUTINE read_array(fid,mm,nn,aa,ustr,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE +! + INTEGER mm, nn, i, j, ismpl +! warning flag + LOGICAL w_flag +! file id + INTEGER fid +! array to fill + DOUBLE PRECISION aa(mm,nn) +! unit string, for error message + character (len=*) :: ustr +! for reading each line separated + character (len=1024) :: line + + w_flag = .false. + IF (ustr==key_char//' units' .OR. & + ustr==key_char//' errors' .OR. & + ustr==key_char//' apriori') THEN + DO j = 1, nn + READ(fid,'(A)',err=200,end=200) line + READ(line,*,err=100,end=100) (aa(i,j),i=1,mm) + GOTO 10 +100 IF (i-1<mm) w_flag = .true. +10 CONTINUE + END DO + IF (w_flag) GOTO 300 + ELSE + DO j = 1, nn + READ(fid,*,err=200,end=200) (aa(i,j),i=1,mm) + END DO + ENDIF + RETURN +! +! error handler +200 WRITE(*,'(3A,1I5,1A,1I5,1A)') 'error: while reading section "', ustr, & + '", to few values (need ', mm, ' in each of the ', nn, ' lines) !' + STOP +300 WRITE(*,'(3A,1I5,1A,1I5,1A)') ' <D> : WARNING while reading section "', ustr, & + '", to few values (need ', mm, ' in each of the ', nn, ' lines) !' + IF (mm==nprop_load) THEN + IF (ustr==key_char//' units') WRITE(*,'(1I3,2A,'//c_npropunit//'(",",1A),1A)') mm, & + ' properties each line : [', (properties(i),i=1,nprop_load), ']' + IF (ustr==key_char//' errors') WRITE(*,'(1I3,2A,'//c_npropunit//'(",",1A),1A)') mm, & + ' property errors each line : [', (properties(i),i=1,nprop_load), ']' + IF (ustr==key_char//' apriori') WRITE(*,'(1I3,2A,'//c_npropunit//'(",",1A),1A)') & + mm, ' apriori values each line : [', (properties(i),i=1,nprop_load), ']' + WRITE(*,*) ' ' + WRITE(*,'(1A)') ' properties:' + DO i = 1, nprop_load + WRITE(*,'(4A)') ' ', properties(i), ': ', doc_properties(i) + END DO + WRITE(*,*) ' ' + END IF + RETURN + END diff --git a/forward/input/read_bc.f90 b/forward/input/read_bc.f90 new file mode 100644 index 0000000..c8b7066 --- /dev/null +++ b/forward/input/read_bc.f90 @@ -0,0 +1,839 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read the boundary condition specifications +!> @param[in] filen number of the opened file +!> @param[in] line current character line +!> @param[in] i_pv physical value / state variable - index +!> @param[in] i_bt boundary type -index +!> @param[in,out] posi number (position of the last one) of boundary points - before and after reading +!> @param[out] ilost number of lost boundary points (reading ignored) +!> @param[in] ismpl local sample index +!> @details +!> read model boundary points\n +!> \n +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. + SUBROUTINE read_bc(filen,line,i_pv,i_bt,posi,ilost,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_conc + use mod_linfos +#ifndef noHDF + use mod_input_file_parser_hdf5 +#endif + IMPLICIT NONE + integer :: i, j, k + integer :: ismpl +! +! number of the opened file + INTEGER filen, posi, ilost, i_errors +! i_bcu : bc-unit +! i_bctp : bc-time period +! i_pv : physical value index +! i_bt : boundary type (dirichlet, neumann) +! i_si : sub index (conc) +! i_dir : direction +! i_records: number of entries for this section + INTEGER i_bcu, i_bctp, i_pv, i_bt, i_si, i_dir, i_records +! d_bcmy: bc-my + DOUBLE PRECISION d_bcmy + + character (len=80) :: line + + LOGICAL, ALLOCATABLE :: tmpbl(:,:,:,:) + INTEGER, ALLOCATABLE :: tmpind(:,:) + DOUBLE PRECISION, ALLOCATABLE :: tmpval(:,:) + + INTEGER lblank, read_direction, i_b, i_e, j_b, j_e, k_b, k_e, ll + INTEGER level_bcindex + + LOGICAL read_simple, read_bctp, read_species, read_bcval, & + l_errign + LOGICAL found, no_ext_link, no_ext_link_int + EXTERNAL found, no_ext_link, no_ext_link_int, lblank, & + read_direction + + character (len=5), dimension (0:6) :: c_dir + DATA c_dir/'none', 'left', 'right', 'front', 'back', 'base', & + 'top'/ + character (len=8) :: c_name + logical :: found_marker + character (len=80) :: full_bc_name + +! if switch used, read one column more (bcindex) + i_bcu = 0 +! 0: do not read bc-units, but read pv-values +! 1: read bc-units +! 2: do not read bc-units and pv-values + level_bcindex = 0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + full_bc_name = trim(line) + if (h5parse_check_attr_exist("bcindex","bc/i"//full_bc_name)) then + call h5parse_read_integer_attribute("bcindex",level_bcindex,"bc/i"//full_bc_name) + end if + else +#endif + CALL get_arg('bcindex',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! prove "r" instead of "read" + IF (line(i:i)=='r') THEN + level_bcindex = 1 + ELSE + level_bcindex = 2 + READ(line(i:j),*) i_bcu +! write(*,'(1A,1I5)') ' bc unit=',i_bcu + END IF + END IF +#ifndef noHDF + end if +#endif + + d_bcmy = 1.0D+18 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("bcmy","bc/"//full_bc_name)) then + call h5parse_read_double_attribute("bcmy",d_bcmy,"bc/"//full_bc_name) + end if + else +#endif + CALL get_arg('bcmy',line,i,j) + IF (i>=1 .AND. j>=i) THEN + READ(line(i:j),*) d_bcmy +! write(*,'(1A,1e16.8)') ' bcmy=',d_bcmy + END IF +#ifndef noHDF + end if +#endif + + i_si = 0 + read_species = .FALSE. + IF (i_pv==pv_conc) read_species = .TRUE. +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("species","bc/i"//full_bc_name)) then + call h5parse_read_integer_attribute("species",i_si,"bc/i"//full_bc_name) + read_species = .FALSE. + end if + else +#endif + CALL get_arg('species',line,i,j) + IF (i>=1 .AND. j>=i) THEN + READ(line(i:j),*) i_si + read_species = .FALSE. +! write(*,'(1A,1I3)') ' speCies=',i_si + END IF +#ifndef noHDF + end if +#endif + + i_bctp = 0 + read_bctp = .TRUE. +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("bctp","bc/i"//full_bc_name)) then + call h5parse_read_integer_attribute("bctp",i_bctp,"bc/i"//full_bc_name) + read_bctp = .False. + end if + else +#endif + CALL get_arg('bctp',line,i,j) + IF (i>=1 .AND. j>=i) THEN + READ(line(i:j),*) i_bctp + read_bctp = .FALSE. +! write(*,'(1A,1I5)') ' bCtp=',i_bCtp + END IF +#ifndef noHDF + end if +#endif + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + read_bcval = .not. h5parse_check_attr_exist("value","bc/i"//full_bc_name) + else +#endif + read_bcval = .TRUE. + CALL get_arg('value',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! prove "i" instead of "init" + IF (line(i:i)=='i') THEN + read_bcval = .FALSE. + ELSE + WRITE(*,'(3A)') 'warning: option "value=', line(i:j), & + '" ignored.' + END IF + END IF +#ifndef noHDF + end if +#endif + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + l_errign = h5parse_check_attr_exist("error","bc/i"//full_bc_name) + else +#endif + l_errign = .FALSE. + CALL get_arg('error',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! prove "i" instead of "ignore" + IF (line(i:i)=='i') THEN + l_errign = .TRUE. + ELSE + WRITE(*,'(3A)') 'warning: option "error=', line(i:j), & + '" ignored.' + END IF + END IF +#ifndef noHDF + end if +#endif + + i_dir = -1 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + l_errign = h5parse_check_attr_exist("error","bc/i"//full_bc_name) + else +#endif + read_simple = .FALSE. + CALL get_arg('simple',line,i,j) + IF (i>=1 .AND. j>=i) THEN + i_dir = read_direction(line(i:j)) + read_simple = .TRUE. +! enable "error=ignore" as default in <simple> case + l_errign = .TRUE. + END IF +#ifndef noHDF + end if +#endif + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("direction","bc/i"//full_bc_name)) then + call h5parse_read_integer_attribute("direction",i_dir,"bc/i"//full_bc_name) + end if + else +#endif + CALL get_arg('direction',line,i,j) + IF (i>=1 .AND. j>=i) THEN + k = read_direction(line(i:j)) + IF (i_dir==-1) THEN + i_dir = k +!debug write(*,'(2A)') ' direCtion=',C_dir(i_dir) + ELSE IF (i_dir/=k) THEN + WRITE(*,'(1A)') 'error: "direction"-"simple" mismatch !' + STOP + END IF + END IF +#ifndef noHDF + end if +#endif + +! zero, should be forbidden !!! + i_dir = max(0,i_dir) +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + i_records = h5parse_read_dimension_size_for_dataset("bc/"//full_bc_name) + else +#endif + i_b = 1 + i_e = i0 + j_b = 1 + j_e = j0 + k_b = 1 + k_e = k0 + IF (read_simple) THEN + IF (i_dir==0) THEN + WRITE(*,*) 'error: simple=none not allowed !!!' + STOP + ELSE IF (i_dir==1) THEN + i_records = j0*k0 + i_b = 1 + i_e = 1 + ELSE IF (i_dir==2) THEN + i_records = j0*k0 + i_b = i0 + i_e = i0 + ELSE IF (i_dir==3) THEN + i_records = i0*k0 + j_b = 1 + j_e = 1 + ELSE IF (i_dir==4) THEN + i_records = i0*k0 + j_b = j0 + j_e = j0 + ELSE IF (i_dir==5) THEN + i_records = i0*j0 + k_b = 1 + k_e = 1 + ELSE IF (i_dir==6) THEN + i_records = i0*j0 + k_b = k0 + k_e = k0 + END IF + ELSE + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(filen,*) i_records + ELSE + READ(line(i:j),*) i_records + END IF + END IF +!debug write(*,'(1A,1I5)') ' reCords=',i_reCords +#ifndef noHDF + end if +#endif + + ALLOCATE(tmpind(i_records,nibc)) + ALLOCATE(tmpval(i_records,ndbc)) + +found_marker = .false. +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + call h5parse_read_2d_double_dataset("bc/"//full_bc_name,tmpval) + call h5parse_read_2d_integer_dataset("bc/i"//full_bc_name,tmpind) + found_marker = .true. + else +#endif + + c_name = pv_name(i_pv) // '_' // bc_name(i_bt) +! sainty check + IF (i_pv==pv_conc .AND. i_si<1 .AND. .NOT. read_species) THEN + WRITE(*,'(1A)') 'error: "species" index invalid!' + STOP + END IF + + IF (no_ext_link_int(i_records,nibc,1,tmpind,'i'//c_name,line) & + .AND. no_ext_link(i_records,ndbc,1,tmpval,c_name,line)) & + THEN + found_marker = .true. + IF (read_simple) THEN +! e.g. [temp=10.d0] +! need : bcindex = ? +! bctp = ? +! species = ? +! simple = ? (direction) +! bcmy = ? + IF (read_species) THEN + WRITE(*,'(1A)') 'error: "species" index missing!!!' + STOP + END IF + IF (level_bcindex==0 .AND. read_bcval) THEN + READ(filen,*,err=1001,end=1001) (tmpval(ll,1),ll=1, & + i_records) + ELSE IF (level_bcindex==2) THEN + DO ll = 1, i_records + tmpval(ll,1) = 0.D0 + END DO + ELSE IF (level_bcindex==1) THEN + WRITE(*,'(1A)') 'error: when "simple=?", then "bcindex=read" not supported!!!' + STOP + END IF + + ll = 0 + DO k = k_b, k_e + DO j = j_b, j_e + DO i = i_b, i_e + ll = ll + 1 + tmpind(ll,cbc_i) = i + tmpind(ll,cbc_j) = j + tmpind(ll,cbc_k) = k + tmpind(ll,cbc_bcu) = i_bcu + tmpind(ll,cbc_bctp) = i_bctp + tmpind(ll,cbc_pv) = i_pv + tmpind(ll,cbc_bt) = i_bt + tmpind(ll,cbc_si) = i_si + tmpind(ll,cbc_dir) = i_dir + tmpval(ll,2) = d_bcmy + END DO + END DO + END DO + ELSE +! init, preset values + DO ll = 1, i_records + tmpind(ll,cbc_bcu) = i_bcu + tmpind(ll,cbc_bctp) = i_bctp + tmpind(ll,cbc_pv) = i_pv + tmpind(ll,cbc_bt) = i_bt + tmpind(ll,cbc_si) = i_si + tmpind(ll,cbc_dir) = i_dir + tmpval(ll,1) = 0.0D0 + tmpval(ll,2) = d_bcmy + READ(filen,'(1A)',err=1000,end=1000) line +! read, overwrite values + IF (level_bcindex==1 .AND. read_bctp .AND. read_species) & + THEN +! e.g. [i=1,j=10,k=3, bc-unit=4, bctp-id=0, species=1] + READ(line,*,err=1002,end=1002) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bcu), tmpind(ll,cbc_bctp), & + tmpind(ll,cbc_si) + ELSE IF (level_bcindex==1 .AND. .NOT. read_bctp .AND. & + read_species) THEN +! e.g. [i=1,j=10,k=3, bc-unit=4, species=1] + READ(line,*,err=1003,end=1003) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bcu), tmpind(ll,cbc_si) + ELSE IF (level_bcindex==1 .AND. read_bctp .AND. & + .NOT. read_species) THEN +! e.g. [i=1,j=10,k=3, bc-unit=4, bctp-id=0] + READ(line,*,err=1004,end=1004) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bcu), tmpind(ll,cbc_bctp) + ELSE IF (level_bcindex==1 .AND. .NOT. read_bctp .AND. & + .NOT. read_species) THEN +! e.g. [i=1,j=10,k=3, bc-unit=4] + READ(line,*,err=1005,end=1005) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bcu) + ELSE IF (level_bcindex==0 .AND. read_bctp .AND. & + read_species .AND. read_bcval) THEN +! e.g. [i=1,j=10,k=3, temp=10.d0, bctp-id=0, species=1] + READ(line,*,err=1006,end=1006) (tmpind(ll,j),j=1,3), & + tmpval(ll,1), tmpind(ll,cbc_bctp), tmpind(ll,cbc_si) + ELSE IF (level_bcindex==0 .AND. .NOT. read_bctp .AND. & + read_species .AND. read_bcval) THEN +! e.g. [i=1,j=10,k=3, temp=10.d0, species=1] + READ(line,*,err=1007,end=1007) (tmpind(ll,j),j=1,3), & + tmpval(ll,1), tmpind(ll,cbc_si) + ELSE IF (level_bcindex==0 .AND. read_bctp .AND. & + .NOT. read_species .AND. read_bcval) THEN +! e.g. [i=1,j=10,k=3, temp=10.d0, bctp-id=0] + READ(line,*,err=1008,end=1008) (tmpind(ll,j),j=1,3), & + tmpval(ll,1), tmpind(ll,cbc_bctp) + ELSE IF (level_bcindex==0 .AND. .NOT. read_bctp .AND. & + .NOT. read_species .AND. read_bcval) THEN +! e.g. [i=1,j=10,k=3, temp=10.d0] + READ(line,*,err=1009,end=1009) (tmpind(ll,j),j=1,3), & + tmpval(ll,1) + ELSE IF (level_bcindex==2 .AND. read_bctp .AND. & + read_species) THEN +! e.g. [i=1,j=10,k=3, bctp-id=0, species=1] + READ(line,*,err=1010,end=1010) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bctp), tmpind(ll,cbc_si) + ELSE IF (level_bcindex==2 .AND. .NOT. read_bctp .AND. & + read_species) THEN +! e.g. [i=1,j=10,k=3, species=1] + READ(line,*,err=1011,end=1011) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_si) + ELSE IF (level_bcindex==2 .AND. read_bctp .AND. & + .NOT. read_species) THEN +! e.g. [i=1,j=10,k=3, bctp-id=0] + READ(line,*,err=1012,end=1012) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bctp) + ELSE IF (level_bcindex==2 .AND. .NOT. read_bctp .AND. & + .NOT. read_species) THEN +! e.g. [i=1,j=10,k=3] + READ(line,*,err=1013,end=1013) (tmpind(ll,j),j=1,3) + ELSE IF (level_bcindex==0 .AND. read_bctp .AND. & + read_species .AND. .NOT. read_bcval) THEN +! e.g. [i=1,j=10,k=3, bctp-id=0, species=1] + READ(line,*,err=1014,end=1006) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bctp), tmpind(ll,cbc_si) + ELSE IF (level_bcindex==0 .AND. .NOT. read_bctp .AND. & + read_species .AND. .NOT. read_bcval) THEN +! e.g. [i=1,j=10,k=3, species=1] + READ(line,*,err=1015,end=1007) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_si) + ELSE IF (level_bcindex==0 .AND. read_bctp .AND. & + .NOT. read_species .AND. .NOT. read_bcval) THEN +! e.g. [i=1,j=10,k=3, bctp-id=0] + READ(line,*,err=1016,end=1008) (tmpind(ll,j),j=1,3), & + tmpind(ll,cbc_bctp) + ELSE IF (level_bcindex==0 .AND. .NOT. read_bctp .AND. & + .NOT. read_species .AND. .NOT. read_bcval) THEN +! e.g. [i=1,j=10,k=3] + READ(line,*,err=1017,end=1009) (tmpind(ll,j),j=1,3) + END IF + end do + end if + end if +#ifndef noHDF + end if +#endif + + if (found_marker) then + found_marker = .false. + if (read_simple) then + do ll = 1, i_records + ! copy value, when "value=init" was speCified + IF ( .NOT. read_bcval) THEN + i = tmpind(ll,cbc_i) + j = tmpind(ll,cbc_j) + k = tmpind(ll,cbc_k) + IF (i_pv==pv_head) tmpval(ll,1) = head(i,j,k, ismpl) + IF (i_pv==pv_pres) tmpval(ll,1) = pres(i,j,k, ismpl) + IF (i_pv==pv_temp) tmpval(ll,1) = temp(i,j,k, ismpl) + IF (i_pv==pv_conc) tmpval(ll,1) = conc(i,j,k,i_si, ismpl) + END IF + end do + else + do ll = 1, i_records + +! +! sanity checks +! i,j,k index check + IF (tmpind(ll,cbc_i)<1 .OR. tmpind(ll,cbc_i)>i0 .OR. & + tmpind(ll,cbc_j)<1 .OR. tmpind(ll,cbc_j)>j0 .OR. & + tmpind(ll,cbc_k)<1 .OR. tmpind(ll,cbc_k)>k0) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: index out of range, at line ', ll, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! pv index check + IF (tmpind(ll,cbc_pv)<1 .OR. tmpind(ll,cbc_pv)>npv) THEN + WRITE(*,'(1A,1I6,1A)') 'error: physical value index out of range [1..3], at line ', ll, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! species index check + IF (tmpind(ll,cbc_si)<0 .OR. tmpind(ll,cbc_si)>ntrans) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: species index out of range, at line ', ll,'!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! direction index check + IF (tmpind(ll,cbc_dir)<0 .OR. tmpind(ll,cbc_dir)>6) THEN + WRITE(*,'(1A,1I6,1A)') 'error: direction index out of range [0..6], at line ', ll, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! wells - direction check + IF (tmpind(ll,cbc_dir)/=0 .AND. tmpind(ll,cbc_bt)==bt_neuw) THEN + WRITE(*,'(1A,1I6,1A)') 'error: well function needs direction index 0, at line ', ll, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! bc-type check + IF (tmpind(ll,cbc_bt)/=bt_diri .AND. & + tmpind(ll,cbc_bt)/=bt_neum .AND. & + tmpind(ll,cbc_bt)/=bt_neuw) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: BC type out of range [1..3], at line ', ll, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF +! bc time period (BCTP) check +! For deeper BCTP checks, a proof for 'tmpind(ll,cbc_bctp)' may be a good idea, +! but the time period table is needed and readed later -> check then ! +! +! copy value, when "value=init" was speCified + IF ( .NOT. read_bcval) THEN + IF (tmpind(ll,cbc_pv)==pv_head) tmpval(ll,1) & + = head(tmpind(ll,cbc_i),tmpind(ll,cbc_j), & + tmpind(ll,cbc_k),ismpl) + IF (tmpind(ll,cbc_pv)==pv_pres) tmpval(ll,1) & + = pres(tmpind(ll,cbc_i),tmpind(ll,cbc_j), & + tmpind(ll,cbc_k),ismpl) + IF (tmpind(ll,cbc_pv)==pv_temp) tmpval(ll,1) & + = temp(tmpind(ll,cbc_i),tmpind(ll,cbc_j), & + tmpind(ll,cbc_k),ismpl) + IF (tmpind(ll,cbc_pv)==pv_conc) tmpval(ll,1) & + = conc(tmpind(ll,cbc_i),tmpind(ll,cbc_j), & + tmpind(ll,cbc_k),tmpind(ll,cbc_si),ismpl) + END IF + END DO + END IF + END IF + +! sanity check + ALLOCATE(tmpbl(I0,J0,K0,max(1,ntrans))) + CALL set_lval(I0*J0*K0*max(1,ntrans), .FALSE., tmpbl) +! mark existing boundary points + DO i = 1, posi + IF (ibc_data(i,cbc_pv)==i_pv) THEN + tmpbl(ibc_data(i,cbc_i),ibc_data(i,cbc_j),ibc_data(i,cbc_k),max(1,ibc_data(i,cbc_si))) = .TRUE. + END IF + END DO +! check for double definition of boundary points + IF (l_errign) THEN +! generate 'ignore' warnings + i_errors = 0 + DO j = 1, i_records + IF (tmpbl(tmpind(j,cbc_i),tmpind(j,cbc_j),tmpind(j,cbc_k),max(1,tmpind(j,cbc_si)))) THEN + IF (read_simple) THEN + i_errors = i_errors +1 + ELSE + WRITE(*,'(1A,3I6,1A)') ' BC ignored at [', & + tmpind(j,cbc_i), tmpind(j,cbc_j), tmpind(j,cbc_k),']' + END IF + tmpind(j,cbc_pv) = -1 + ilost = ilost + 1 + END IF + END DO + IF (read_simple .AND. i_errors>0) THEN + WRITE(*,'(1A,1I6,1A)') ' ',i_errors," BC's ignored (SIMPLE mode)" + END IF + ELSE +! generate errors + i_errors = 0 + DO j = 1, i_records + IF (tmpbl(tmpind(j,cbc_i),tmpind(j,cbc_j),tmpind(j,cbc_k),max(1,tmpind(j,cbc_si)))) THEN + WRITE(*,'(1A,3(1X,1I4),1A,1I1,1A,1I3,1A)') & + ' double defined type at [', tmpind(j,cbc_i), tmpind(j,cbc_j), tmpind(j,cbc_k), & + ' ],type=', i_pv,',species=', tmpind(j,cbc_si),', (different BC type ?) !' + i_errors = i_errors +1 + END IF + END DO + IF (i_errors.gt.0) THEN + WRITE(*,'(1A)') 'error: to many invalid declarations above!!!' + STOP + END IF + END IF + DEALLOCATE(tmpbl) +! + DO i = 1, i_records + IF (tmpind(i,cbc_pv)>=0) THEN + posi = posi + 1 + DO j = 1, nibc + ibc_data(posi,j) = tmpind(i,j) + END DO + DO j = 1, ndbc + dbc_data(posi,j,ismpl) = tmpval(i,j) + END DO +! convert [MPa] into [Pa] + IF (ibc_data(posi,cbc_pv)==pv_pres .AND. read_bcval) & + dbc_data(posi,1,ismpl) = dbc_data(posi,1,ismpl)*pa_conv +! + bc_maxunits = max(bc_maxunits,tmpind(i,cbc_bcu)) + IF ((tmpind(i,cbc_bcu)>nunits) .OR. (tmpind(i, & + cbc_bcu)<0)) THEN + WRITE(*,'(1A,1I7,1A)') & + 'error: bc-unit number out of range, at line ', i, '!' + STOP + END IF + END IF + END DO +! + WRITE(*,'(4A)',advance='NO') ' [R] : ', pv_name(i_pv), ' ', & + bc_name(i_bt) + IF (read_simple) THEN + WRITE(*,'(3A,1I6,1A)',advance='NO') ', simple=', & + c_dir(i_dir), ', (size=', i_records, ')' + ELSE + WRITE(*,'(3A,1I6)',advance='NO') ', direction=', & + c_dir(i_dir), ', records=', i_records + END IF + WRITE(*,'(1A,1e12.4)',advance='NO') ', bcmy=', d_bcmy + IF (level_bcindex==1) THEN + WRITE(*,'(1A)',advance='NO') ', bcindex=read' + END IF + IF (level_bcindex==2) THEN + WRITE(*,'(1A,1I4)',advance='NO') ', bcindex=', i_bcu + END IF + IF (i_bctp/=0) WRITE(*,'(1A,1I4)',advance='NO') ', bctp=', & + i_bctp + IF (i_si/=0) WRITE(*,'(1A,1I4)',advance='NO') ', species=', & + i_si + IF (l_errign) WRITE(*,'(1A)',advance='NO') ', error=ignore' + WRITE(*,'(1A,1I6,1A)') ', (offset=', posi - i_records + 1, & + ')' +! + + DEALLOCATE(tmpval) + DEALLOCATE(tmpind) +! + RETURN + +! ERROR handler +1000 WRITE(*,'(1A)') 'error: expect a BC data line' + STOP +1001 WRITE(*,'(1A)') 'error: to few values - "simple=?" specified' + WRITE(*,'(1A)') ' expected: I0*J0*K0 x [bc-value]' + STOP +1002 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=read" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-unit,tpbc-id,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1003 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=read,bctp=?" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-unit,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1004 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=read,species=?" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-unit,tpbc-id]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1005 WRITE(*,'(1A)') 'error: to few values - "bcindex=read,bctp=?,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,bc-unit]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1006 WRITE(*,'(1A)') 'error: to few values - no option specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-value,tpbc-id,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1007 WRITE(*,'(1A)') 'error: to few values - "bctp=?" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-value,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1008 WRITE(*,'(1A)') & + 'error: to few values - "species=?" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,bc-value,tpbc-id]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1009 WRITE(*,'(1A)') & + 'error: to few values - "bctp=?,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,bc-value]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1010 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=?" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,tpbc-id,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1011 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=?,bctp=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1012 WRITE(*,'(1A)') & + 'error: to few values - "bcindex=?,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,tpbc-id]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1013 WRITE(*,'(1A)') 'error: to few values - "bcindex=?,bctp=?,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1014 WRITE(*,'(1A)') & + 'error: to few values - "value=init" specified' + WRITE(*,'(1A)') & + ' expected: records x [i,j,k,tpbc-id,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1015 WRITE(*,'(1A)') & + 'error: to few values - "value=init,bctp=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,species]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1016 WRITE(*,'(1A)') & + 'error: to few values - "value=init,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k,tpbc-id]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1017 WRITE(*,'(1A)') 'error: to few values - "value=init,bctp=?,species=?" specified' + WRITE(*,'(1A)') ' expected: records x [i,j,k]' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END + +!> @brief sort the boundary points, physical value order +!> @param[in] ismpl local sample index +!> @details +!>sort the boundary points, physical value order\n + SUBROUTINE sort_bc(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_linfos + IMPLICIT NONE + integer :: i, j + integer :: ismpl + INTEGER, ALLOCATABLE :: tmpind(:,:) + DOUBLE PRECISION, ALLOCATABLE :: tmpval(:,:) + + + ALLOCATE(tmpind(nbc_data,nibc)) + ALLOCATE(tmpval(nbc_data,ndbc)) + + first_flow = nbc_data + 1 + last_flow = 0 + IF (head_active .OR. pres_active) THEN + DO i = 1, nbc_data + IF (ibc_data(i,cbc_pv)==pv_head.OR.ibc_data(i,cbc_pv)==pv_pres) THEN + last_flow = last_flow + 1 + first_flow = min(first_flow,last_flow) + DO j = 1, nibc + tmpind(last_flow,j) = ibc_data(i,j) + END DO + DO j = 1, ndbc + tmpval(last_flow,j) = dbc_data(i,j,ismpl) + END DO + END IF + END DO + END IF + + first_temp = nbc_data + 1 + last_temp = last_flow + IF (temp_active) THEN + DO i = 1, nbc_data + IF (ibc_data(i,cbc_pv)==pv_temp) THEN + last_temp = last_temp + 1 + first_temp = min(first_temp,last_temp) + DO j = 1, nibc + tmpind(last_temp,j) = ibc_data(i,j) + END DO + DO j = 1, ndbc + tmpval(last_temp,j) = dbc_data(i,j,ismpl) + END DO + END IF + END DO + END IF + + first_conc = nbc_data + 1 + last_conc = last_temp + IF (trans_active) THEN + DO i = 1, nbc_data + IF (ibc_data(i,cbc_pv)==pv_conc) THEN + last_conc = last_conc + 1 + first_conc = min(first_conc,last_conc) + DO j = 1, nibc + tmpind(last_conc,j) = ibc_data(i,j) + END DO + DO j = 1, ndbc + tmpval(last_conc,j) = dbc_data(i,j,ismpl) + END DO + END IF + END DO + END IF + +! copy back sorted values + DO j = 1, nibc + DO i = 1, nbc_data + ibc_data(i,j) = tmpind(i,j) + END DO + END DO + DO j = 1, ndbc + DO i = 1, nbc_data + dbc_data(i,j,ismpl) = tmpval(i,j) + END DO + END DO + + DEALLOCATE(tmpval) + DEALLOCATE(tmpind) + + RETURN + END diff --git a/forward/input/read_check.f90 b/forward/input/read_check.f90 new file mode 100644 index 0000000..68aee85 --- /dev/null +++ b/forward/input/read_check.f90 @@ -0,0 +1,295 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check parameter / section - definition +!> @param[in] filename model file name + SUBROUTINE read_check(filename) + use mod_genrl + IMPLICIT NONE + integer :: k + character (len=80) :: filename + character (len=80) :: line + LOGICAL phi_style + INTEGER ifil, locstr, f_entry, lblank, line_count + EXTERNAL locstr, lblank + INTEGER i_default + INTEGER (kind=8) :: i_64, test +! Integer compatibility test for BLAS and LAPACK +! both must be from the same size as the default integer size + i_default = 131072 + i_64 = 131072 + i_default = i_default*i_default + i_64 = i_64*i_64 + IF (i_default==i_64) THEN + test = 0 +#ifdef BLAS32 + test = 1 +#endif +#ifdef LAPACK32 + test = 1 +#endif + IF (test==1) THEN + WRITE(*,'(2A)') 'Integer compatibility test for', & + ' BLAS and LAPACK library: [failure]' + WRITE(*,*) & + 'Please determine the current integer size type' + WRITE(*,*) ' of your BLAS and LAPACK library, both must' + WRITE(*,*) & + ' have the same size and equal to the one used' + WRITE(*,*) ' by the compiler for this program binary !' + STOP + END IF + END IF + WRITE(*,*) + WRITE(*,*) ' checking input definitions:' + WRITE(*,*) ' from file "', filename(:lblank(filename)), & + '"' +! init counter for hard errors (old style - not longer supported) + k = 0 +! read file + phi_style = .FALSE. + ifil = 77 + line_count = 0 + OPEN(ifil,file=filename,status='old') +10 CONTINUE + READ(ifil,'(A)',end=20) line + line_count = line_count + 1 + IF (line(1:1)/='#') GO TO 10 + f_entry = 0 +! forward, general + f_entry = f_entry + locstr(line,key_char//' title') + f_entry = f_entry + locstr(line,key_char//' PROPS') + f_entry = f_entry + locstr(line,key_char//' USER') + f_entry = f_entry + locstr(line,key_char//' linfo') + f_entry = f_entry + locstr(line,key_char//' runmode') + f_entry = f_entry + locstr(line,key_char//' grid') + f_entry = f_entry + locstr(line,key_char//' nlsolve') + f_entry = f_entry + locstr(line,key_char//' active') + f_entry = f_entry + locstr(line,key_char//' rref') + f_entry = f_entry + locstr(line,key_char//' grav') + f_entry = f_entry + locstr(line,key_char//' rhocm') + f_entry = f_entry + locstr(line,key_char//' hpf') + f_entry = f_entry + locstr(line,key_char//' delx') + f_entry = f_entry + locstr(line,key_char//' dely') + f_entry = f_entry + locstr(line,key_char//' delz') + f_entry = f_entry + locstr(line,key_char//' uindex') + f_entry = f_entry + locstr(line,key_char//' units') + f_entry = f_entry + locstr(line,key_char//' bcunits') + f_entry = f_entry + locstr(line,key_char//' split units') +! forward, output + f_entry = f_entry + locstr(line,key_char//' borehole log') + f_entry = f_entry + locstr(line,key_char//' disable small output') + f_entry = f_entry + locstr(line,key_char//' disable output') + f_entry = f_entry + locstr(line,key_char//' write output') + f_entry = f_entry + locstr(line,key_char//' read output') +! forward, data + f_entry = f_entry + locstr(line,key_char//' data') +! solver, convergency, flow + f_entry = f_entry + locstr(line,key_char//' lsolvef') + f_entry = f_entry + locstr(line,key_char//' error lsolvef') + f_entry = f_entry + locstr(line,key_char//' maxiter lsolvef') + f_entry = f_entry + locstr(line,key_char//' name lsolvef') + f_entry = f_entry + locstr(line,key_char//' criteria lsolvef') + f_entry = f_entry + locstr(line,key_char//' precondition lsolvef') + f_entry = f_entry + locstr(line,key_char//' omf') + f_entry = f_entry + locstr(line,key_char//' nliterf') + f_entry = f_entry + locstr(line,key_char//' grad nliterf') +! solver, convergency, temperature + f_entry = f_entry + locstr(line,key_char//' lsolvet') + f_entry = f_entry + locstr(line,key_char//' error lsolvet') + f_entry = f_entry + locstr(line,key_char//' maxiter lsolvet') + f_entry = f_entry + locstr(line,key_char//' name lsolvet') + f_entry = f_entry + locstr(line,key_char//' criteria lsolvet') + f_entry = f_entry + locstr(line,key_char//' precondition lsolvet') + f_entry = f_entry + locstr(line,key_char//' omt') + f_entry = f_entry + locstr(line,key_char//' nlitert') + f_entry = f_entry + locstr(line,key_char//' grad nlitert') +! solver, convergency, concentration + f_entry = f_entry + locstr(line,key_char//' lsolvec') + f_entry = f_entry + locstr(line,key_char//' error lsolvec') + f_entry = f_entry + locstr(line,key_char//' maxiter lsolvec') + f_entry = f_entry + locstr(line,key_char//' name lsolvec') + f_entry = f_entry + locstr(line,key_char//' criteria lsolvec') + f_entry = f_entry + locstr(line,key_char//' precondition lsolvec') + f_entry = f_entry + locstr(line,key_char//' nliterc') + f_entry = f_entry + locstr(line,key_char//' grad nliterc') +! debug special +#ifdef DEBUG + f_entry = f_entry + locstr(line,key_char//' debug output times') +#endif +! +! forward, state variables + f_entry = f_entry + locstr(line,key_char//' head init') + f_entry = f_entry + locstr(line,key_char//' temp init') + f_entry = f_entry + locstr(line,key_char//' pres init') +! forward, boundary conditions + f_entry = f_entry + locstr(line,key_char//' head bcd') + f_entry = f_entry + locstr(line,key_char//' head bcn') + f_entry = f_entry + locstr(line,key_char//' pres bcd') + f_entry = f_entry + locstr(line,key_char//' pres bcn') + f_entry = f_entry + locstr(line,key_char//' temp bcd') + f_entry = f_entry + locstr(line,key_char//' temp bcn') + f_entry = f_entry + locstr(line,key_char//' conc bcd') + f_entry = f_entry + locstr(line,key_char//' conc bcn') +! forward, time + f_entry = f_entry + locstr(line,key_char//' timestep control') + f_entry = f_entry + locstr(line,key_char//' tunit') + f_entry = f_entry + locstr(line,key_char//' tstart') + f_entry = f_entry + locstr(line,key_char//' titer') + f_entry = f_entry + locstr(line,key_char//' time periods') + f_entry = f_entry + locstr(line,key_char//' bc time periods') + f_entry = f_entry + locstr(line,key_char//' monitor') + f_entry = f_entry + locstr(line,key_char//' output times') + f_entry = f_entry + locstr(line,key_char//' file output') +! transport (chemical) + f_entry = f_entry + locstr(line,key_char//' ntrans') + f_entry = f_entry + locstr(line,key_char//' tracer') + f_entry = f_entry + locstr(line,key_char//' transpar') +! simulation + f_entry = f_entry + locstr(line,key_char//' simulate') + f_entry = f_entry + locstr(line,key_char//' samples') + f_entry = f_entry + locstr(line,key_char//' parameter group') +! ENKF + f_entry = f_entry + locstr(line,key_char//' enkf postcompute') + f_entry = f_entry + locstr(line,key_char//' enkf iter') +! AD deterministic inverse + f_entry = f_entry + locstr(line,key_char//' inverse') + f_entry = f_entry + locstr(line,key_char//' enable property') + f_entry = f_entry + locstr(line,key_char//' enable unit') +! inverse, property units + f_entry = f_entry + locstr(line,key_char//' errors') + f_entry = f_entry + locstr(line,key_char//' apriori') + f_entry = f_entry + locstr(line,key_char//' weight property') + f_entry = f_entry + locstr(line,key_char//' optimize property') +! inverse, boundary conditions + f_entry = f_entry + locstr(line,key_char//' bcerrors') + f_entry = f_entry + locstr(line,key_char//' bcapriori') + f_entry = f_entry + locstr(line,key_char//' weight bc') + f_entry = f_entry + locstr(line,key_char//' optimize bc') +! inverse, time + f_entry = f_entry + locstr(line,key_char//' tperrors') + f_entry = f_entry + locstr(line,key_char//' tpapriori') + f_entry = f_entry + locstr(line,key_char//' optimize tp') +! inverse, weighting +!AW f_entry = f_entry + locstr(line,key_char//' weight tp') + f_entry = f_entry + locstr(line,key_char//' weight para') + f_entry = f_entry + locstr(line,key_char//' weight data') +! -------- +! +! automatic generated check sections, by Makfile 'check_section' + f_entry = f_entry + locstr(line,key_char//' set') + f_entry = f_entry + locstr(line,key_char//' velocity') + f_entry = f_entry + locstr(line,key_char//' mfd') + f_entry = f_entry + locstr(line,key_char//' h5parse data file') + f_entry = f_entry + locstr(line,key_char//' simtime') + f_entry = f_entry + locstr(line,key_char//' jacoby') + f_entry = f_entry + locstr(line,key_char//' itimestep') + f_entry = f_entry + locstr(line,key_char//' iter_inv') + f_entry = f_entry + locstr(line,key_char//' variable step size') + f_entry = f_entry + locstr(line,key_char//' nliters') + f_entry = f_entry + locstr(line,key_char//' grad nliters') + f_entry = f_entry + locstr(line,key_char//' cindex') + f_entry = f_entry + locstr(line,key_char//' simul') + f_entry = f_entry + locstr(line,key_char//' enkf') + f_entry = f_entry + locstr(line,key_char//' prop limit') + f_entry = f_entry + locstr(line,key_char//' ilu block size') + f_entry = f_entry + locstr(line,key_char//' ZETA') + f_entry = f_entry + locstr(line,key_char//' THETA') + f_entry = f_entry + locstr(line,key_char//' PSI') + f_entry = f_entry + locstr(line,key_char//' LAMDA') + f_entry = f_entry + locstr(line,key_char//' C0') + f_entry = f_entry + locstr(line,key_char//' B2') + f_entry = f_entry + locstr(line,key_char//' B1') + f_entry = f_entry + locstr(line,key_char//' B0') + f_entry = f_entry + locstr(line,key_char//' species') + f_entry = f_entry + locstr(line,key_char//' secondary') + f_entry = f_entry + locstr(line,key_char//' sec_comp') + f_entry = f_entry + locstr(line,key_char//' parameter species') + f_entry = f_entry + locstr(line,key_char//' minerals') + f_entry = f_entry + locstr(line,key_char//' kinetic rate laws') + f_entry = f_entry + locstr(line,key_char//' inhibitors') + f_entry = f_entry + locstr(line,key_char//' subsample') + f_entry = f_entry + locstr(line,key_char//' bc standard deviation') + f_entry = f_entry + locstr(line,key_char//' bc group') + f_entry = f_entry + locstr(line,key_char//' regular') + f_entry = f_entry + locstr(line,key_char//' standard deviation') + f_entry = f_entry + locstr(line,key_char//' covar prior para') + f_entry = f_entry + locstr(line,key_char//' covar prior data') + f_entry = f_entry + locstr(line,key_char//' fluid props') + f_entry = f_entry + locstr(line,key_char//' archie') + f_entry = f_entry + locstr(line,key_char//' gas props') + f_entry = f_entry + locstr(line,key_char//' rhod') + f_entry = f_entry + locstr(line,key_char//' liq init') + f_entry = f_entry + locstr(line,key_char//' freeze_b') + f_entry = f_entry + locstr(line,key_char//' freeze_a') + f_entry = f_entry + locstr(line,key_char//' k_freeze') + f_entry = f_entry + locstr(line,key_char//' fracpar') +! -------- + IF (f_entry==0) WRITE(*,'(A,I6,3A)') 'warning: ignore line ', & + line_count, ': "', line(:lblank(line)), '"' +! compatibility check + IF (locstr(line,key_char//' phi')==1) phi_style = .TRUE. +! !!! no longer supported section, stoping later !!! + k = k + locstr(line,key_char//' left head') + k = k + locstr(line,key_char//' left flow') + k = k + locstr(line,key_char//' right head') + k = k + locstr(line,key_char//' right flow') + k = k + locstr(line,key_char//' front head') + k = k + locstr(line,key_char//' front flow') + k = k + locstr(line,key_char//' back head') + k = k + locstr(line,key_char//' back flow') + k = k + locstr(line,key_char//' base head') + k = k + locstr(line,key_char//' base flow') + k = k + locstr(line,key_char//' top head') + k = k + locstr(line,key_char//' top flow') + k = k + locstr(line,key_char//' left temperature') + k = k + locstr(line,key_char//' left heat flow') + k = k + locstr(line,key_char//' right temperature') + k = k + locstr(line,key_char//' right heat flow') + k = k + locstr(line,key_char//' front temperature') + k = k + locstr(line,key_char//' front heat flow') + k = k + locstr(line,key_char//' back temperature') + k = k + locstr(line,key_char//' back heat flow') + k = k + locstr(line,key_char//' base temperature') + k = k + locstr(line,key_char//' base heat flow') + k = k + locstr(line,key_char//' top temperature') + k = k + locstr(line,key_char//' top heat flow') + GO TO 10 +! close project config file +20 CLOSE(ifil) + IF (k>0) THEN + WRITE(*,'(1A)') & + 'error: old BC sections no longer supported!!!' + STOP + END IF +! compatibility check fails, then message out + IF (phi_style) THEN + WRITE(*,*) + WRITE(*,'(1A)') & + 'error: found old "PHI" style definitions !!!' + WRITE(*,'(1A)') & + ' Please change all "phi" into "head" occurrence !' + WRITE(*,*) + STOP + END IF + RETURN + END diff --git a/forward/input/read_control.f90 b/forward/input/read_control.f90 new file mode 100644 index 0000000..7a17b05 --- /dev/null +++ b/forward/input/read_control.f90 @@ -0,0 +1,79 @@ + +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read control sections for the external file-infrastructure +!> @param[in] filename +!> @param[in] ismpl local sample index + SUBROUTINE read_control(filename,ismpl) + use mod_genrl + use mod_genrlc + IMPLICIT NONE + integer :: ismpl + integer :: i, j + + character (len=*) :: filename + character (len=5000) :: line + LOGICAL found + EXTERNAL found + INTRINSIC trim + +! External input file switch not set + if (.not. read_external_input) then + filename_data = filename + return + end if + +! open file + OPEN(79,file=filename,status='old') + WRITE(*,*) ' ' + WRITE(*,*) ' reading external file control' + WRITE(*,*) ' ' +! + filename_data = filename + IF (runmode>=1) THEN + IF (found(79,key_char//' data: external file',line,.FALSE.)) THEN + CALL get_arg('file',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=100,end=100) filename_data + ELSE + READ(line(i:j),*) filename_data + END IF + WRITE(*,*) ' [R] : external file "'//trim(filename_data)//'" for DATA' +! ELSE +! WRITE(*,*) ' <D> : no external file for DATA' + END IF + END IF +! + CLOSE(79) + RETURN +! +! error handling +100 WRITE(*,'(1A)') 'error: no external file name found in section "data: external file"!' + STOP +101 WRITE(*,'(1A)') 'error: no external file name found in section "simul: external file"!' + STOP +102 WRITE(*,'(1A)') 'error: no external file name found in section "enkf: external file"!' + STOP +103 WRITE(*,'(1A)') 'error: no external file name found in section "inverse: external file"!' + STOP + END diff --git a/forward/input/read_data.f90 b/forward/input/read_data.f90 new file mode 100644 index 0000000..b48c0a6 --- /dev/null +++ b/forward/input/read_data.f90 @@ -0,0 +1,656 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read observed data and allocate fields +!> @param[in] filename file name +!> @param[in] ismpl local sample index +!> @details +!> details see in documentation "read_observed_data.pdf"\n + SUBROUTINE read_data(filename,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_time + use mod_conc + use mod_data + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + character (len=80) :: filename + character (len=80) :: line + INTEGER locstr, lblank, type, ozone, i2, i3, ll, & + ndata_sections, tmplen + ! INTEGER c_i, c_j, c_k + INTEGER level_timer, i_si, i_obs + DOUBLE PRECISION d_timer + LOGICAL found, no_ext_link, no_ext_link_int + ! LOGICAL incomp_bc + LOGICAL read_species, read_obs, read_absolute + INTEGER, ALLOCATABLE :: tmp_idata(:,:) + DOUBLE PRECISION, ALLOCATABLE :: tmp_data(:,:) + EXTERNAL locstr, found, no_ext_link, no_ext_link_int, lblank + + +! read file + OPEN(79,file=filename,status='old') + +! init HDF5 support, when available + CALL open_hdf5(' ') + + WRITE(*,*) + WRITE(*,*) ' reading observed data' + WRITE(*,*) ' from file "', filename(:lblank(filename)), & + '"' + WRITE(*,*) + +! init counter + ndata_h = 0 + ndata_t = 0 + ndata_c = 0 + ndata_p = 0 + ndata_s = 0 + ndata_b = 0 + +! count the number of observed data entries (sections and entries) + REWIND 79 + ndata_sections = 0 + ndata = 0 + +10 READ(79,'(1A)',end=11) line + i = locstr(line,key_char//' data') +! data line? + IF (i==1) THEN +! increase number of sections + ndata_sections = ndata_sections + 1 + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF +! increase number of entries + ndata = ndata + tmplen + END IF +! read next line, up to the end of file + GO TO 10 + +! restart file +11 REWIND 79 + + ALLOCATE(tmp_idata(max(ndata,1),n_idata)) + ALLOCATE(tmp_data(max(ndata,1),n_ddata)) + ll = 0 + + DO i3 = 1, ndata_sections + IF (found(79,key_char//' data',line,.TRUE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF + +! time dependent data, if switch used, read one column more + d_timer = max_simtime/tunit +! 0: do not read timers +! 1: read timers +! 2: use the given timer for all records + level_timer = 0 + CALL get_arg('timer',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! prove "r" instead of "read" + IF (line(i:i)=='r') THEN + level_timer = 1 + ELSE + level_timer = 2 + READ(line(i:j),*,err=901) d_timer +! write(*,'(1A,1e16.8)') ' timer=',d_timer + END IF + END IF + +! species for concentration + i_si = 0 + read_species = .TRUE. + CALL get_arg('species',line,i,j) + IF (i>=1 .AND. j>=i) THEN + READ(line(i:j),*) i_si + read_species = .FALSE. +! write(*,'(1A,1I3)') ' speCies=',i_si + END IF + +! position type + read_absolute = .FALSE. + CALL get_arg('pos',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! if (line(i:i).eq.'index') read_absolute = .false. +! instead of prove "abs" or "index" + IF (line(i:i)=='a') read_absolute = .TRUE. +! write(*,*) ' position absolute=',read_absolute + END IF + +! observation point index + i_obs = 0 + read_obs = .TRUE. + CALL get_arg('obs',line,i,j) + IF (i>=1 .AND. j>=i) THEN + READ(line(i:j),*) i_obs + read_obs = .FALSE. +! write(*,'(1A,1I3)') ' obs=',i_obs + END IF + + WRITE(*,'(A,I6)') ' [R] : observed data nodes, records=' & + , tmplen +! sanity check + IF (level_timer>=1 .AND. .NOT. transient) THEN + WRITE(*,'(2A)') & + 'error: "timer" is specified for the data', & + ' input, but the model is steady state !' + STOP + END IF + + IF (no_ext_link_int(tmplen,n_idata,1,tmp_idata,'idata', & + line) .OR. no_ext_link(tmplen,n_ddata,1,tmp_data, & + 'data',line)) THEN + DO j = 1, tmplen +! record counter + ll = ll + 1 + READ(79,'(1A)') line + tmp_data(ll,cdd_time) = d_timer + tmp_idata(ll,cid_si) = i_si + tmp_idata(ll,cid_obs) = i_obs + +! ---------- + IF ( .NOT. read_absolute) THEN +! index position + IF (level_timer==1 .AND. read_obs) THEN + READ(line,*,err=1001,end=1001) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_idata(ll,k),k=cid_i, & + cid_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_obs) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=1002,end=1002) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_idata(ll,k),k=cid_i, & + cid_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_si), tmp_idata(ll,cid_obs) + ELSE IF (level_timer==1 .AND. .NOT. read_obs) THEN + READ(line,*,err=1003,end=1003) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_idata(ll,k),k=cid_i, & + cid_k), tmp_idata(ll,cid_pv) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=1004,end=1004) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_idata(ll,k),k=cid_i, & + cid_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_si) + ELSE IF (level_timer/=1 .AND. read_obs) THEN + READ(line,*,err=1005,end=1005) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + (tmp_idata(ll,k),k=cid_i,cid_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_obs) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=1006,end=1006) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + (tmp_idata(ll,k),k=cid_i,cid_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_si), & + tmp_idata(ll,cid_obs) + ELSE IF (level_timer/=1 .AND. .NOT. read_obs) THEN + READ(line,*,err=1007,end=1007) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + (tmp_idata(ll,k),k=cid_i,cid_k), & + tmp_idata(ll,cid_pv) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=1008,end=1008) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + (tmp_idata(ll,k),k=cid_i,cid_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_si) + END IF +! ---------- + ELSE +! ---------- +! absolute position + IF (level_timer==1 .AND. read_obs) THEN + READ(line,*,err=2001,end=2001) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_data(ll,k),k=cdd_i, & + cdd_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_obs) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=2002,end=2002) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_data(ll,k),k=cdd_i, & + cdd_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_si), tmp_idata(ll,cid_obs) + ELSE IF (level_timer==1 .AND. .NOT. read_obs) THEN + READ(line,*,err=2003,end=2003) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_data(ll,k),k=cdd_i, & + cdd_k), tmp_idata(ll,cid_pv) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=2004,end=2004) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + tmp_data(ll,cdd_time), (tmp_data(ll,k),k=cdd_i, & + cdd_k), tmp_idata(ll,cid_pv), & + tmp_idata(ll,cid_si) + ELSE IF (level_timer/=1 .AND. read_obs) THEN + READ(line,*,err=2005,end=2005) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + (tmp_data(ll,k),k=cdd_i,cdd_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_obs) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=2006,end=2006) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + (tmp_data(ll,k),k=cdd_i,cdd_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_si), & + tmp_idata(ll,cid_obs) + ELSE IF (level_timer/=1 .AND. .NOT. read_obs) THEN + READ(line,*,err=2007,end=2007) tmp_data(ll, & + cdd_pv), tmp_data(ll,cdd_w), & + (tmp_data(ll,k),k=cdd_i,cdd_k), & + tmp_idata(ll,cid_pv) +! re-read with sub-index (species) + IF (tmp_idata(ll,cid_pv)==pv_conc .AND. & + read_species) READ(line,*,err=2008,end=2008) & + tmp_data(ll,cdd_pv), tmp_data(ll,cdd_w), & + (tmp_data(ll,k),k=cdd_i,cdd_k), & + tmp_idata(ll,cid_pv), tmp_idata(ll,cid_si) + END IF + END IF +! ---------- + + IF (read_absolute) THEN +! search index values for x,y,z + tmp_idata(ll,cid_i) = 0 + DO k = 1, i0 + IF (delxa(k)-0.5D0*delx(k)<=tmp_data(ll,cdd_i)) & + tmp_idata(ll,cid_i) = k + END DO + tmp_idata(ll,cid_j) = 0 + DO k = 1, j0 + IF (delya(k)-0.5D0*dely(k)<=tmp_data(ll,cdd_j)) & + tmp_idata(ll,cid_j) = k + END DO + tmp_idata(ll,cid_k) = 0 + DO k = 1, k0 + IF (delza(k)-0.5D0*delz(k)<=tmp_data(ll,cdd_k)) & + tmp_idata(ll,cid_k) = k + END DO + ELSE +! convert index i,j,k into absolute postion + tmp_data(ll,cdd_i) = delxa(tmp_idata(ll,cid_i)) + tmp_data(ll,cdd_j) = delya(tmp_idata(ll,cid_j)) + tmp_data(ll,cdd_k) = delza(tmp_idata(ll,cid_k)) + END IF + +! modify with 'tunit' + tmp_data(ll,cdd_time) = tmp_data(ll,cdd_time)*tunit +! sanity checks + IF (tmp_data(ll,cdd_time)<simtime_0 .OR. & + tmp_data(ll,cdd_time)>max_simtime) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: timer value out of range, at line ', j, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF + IF (tmp_data(ll,cdd_w)<dabs(1.0d-10*tmp_data(ll,cdd_pv))) THEN + tmp_data(ll,cdd_w)=max(dabs(1.0d-10*tmp_data(ll,cdd_pv)),1.0d-99) + WRITE(*,'(1A,1I6,1A,1G12.4,1A)') & + 'warning: given error seems to be to small, at line ', j, & + ', cutting them to ',tmp_data(ll,cdd_w),'!' + END IF + IF (tmp_idata(ll,cid_i)<1 .OR. & + tmp_idata(ll,cid_i)>i0 .OR. & + tmp_idata(ll,cid_j)<1 .OR. & + tmp_idata(ll,cid_j)>j0 .OR. & + tmp_idata(ll,cid_k)<1 .OR. tmp_idata(ll,cid_k)>k0) & + THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: index out of range, at line ', j, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF + IF (tmp_data(ll,cdd_i)<0.0D0 .OR. & + tmp_data(ll,cdd_i)>delxa(i0)+0.5D0*delx(i0) .OR. & + tmp_data(ll,cdd_j)<0.0D0 .OR. & + tmp_data(ll,cdd_j)>delya(j0)+0.5D0*dely(j0) .OR. & + tmp_data(ll,cdd_k)<0.0D0 .OR. & + tmp_data(ll,cdd_k)>delza(k0)+0.5D0*delz(k0)) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: absolute position out of range, at line ', & + j, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF + IF (tmp_idata(ll,cid_pv)<1 .OR. & + tmp_idata(ll,cid_pv)>npv) THEN + WRITE(*,'(1A,1I1,1A,1I6,1A)') & + 'error: physical value index out of range [1..', & + npv, '], at line ', j, '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF + IF (tmp_idata(ll,cid_si)<0 .OR. & + tmp_idata(ll,cid_si)>ntrans) THEN + WRITE(*,'(1A,1I6,1A)') & + 'error: species index out of range, at line ', j, & + '!' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END IF + END DO + END IF + END IF + END DO +! sanity check + IF (ll/=ndata) THEN + WRITE(*,'(1A)') 'error: lost some data in "read_data.f" !' + WRITE(*,*) ' searching:', ndata, ', but reading:', ll + STOP + END IF + + IF (ndata>=1) THEN +! compare data and boundaries, eleminate one of them when on the same position + k = 0 + DO j = 1, ndata + DO i = 1, nbc_data +! only dirichlet boundaries + IF ((tmp_idata(j,cid_i)==ibc_data(i, & + cbc_i)) .AND. (tmp_idata(j,cid_j)==ibc_data(i, & + cbc_j)) .AND. (tmp_idata(j,cid_k)==ibc_data(i, & + cbc_k)) .AND. (bt_diri==ibc_data(i, & + cbc_bt)) .AND. (tmp_idata(j,cid_pv)==ibc_data(i, & + cbc_pv))) THEN +! disable them, later delete/ignore +#ifndef DbB +! BbD, Boundaries before Data + tmp_idata(j,cid_pv) = 0 +#else +! DbB, Data before Boundaries + ibc_data(i,cbc_pv) = -ibc_data(i,cbc_pv) +#endif + k = k + 1 + ELSE +! dont change, leave them + END IF + END DO + END DO + + ll = 0 +! compare data with data, eleminate one of them when on the same position + DO j = 1, ndata + DO i = 1, ndata +! only dirichlet boundaries + IF ((tmp_idata(i,cid_i)==tmp_idata(j, & + cid_i)) .AND. (tmp_idata(i,cid_j)==tmp_idata(j, & + cid_j)) .AND. (tmp_idata(i,cid_k)==tmp_idata(j, & + cid_k)) .AND. (tmp_idata(i,cid_pv)==tmp_idata(j, & + cid_pv)) .AND. (tmp_idata(i,cid_si)==tmp_idata(j, & + cid_si)) .AND. (tmp_data(i,cdd_time)==tmp_data(j, & + cdd_time)) .AND. (i/=j) .AND. & + tmp_idata(j,cid_pv)/=0) THEN +! disable them, later delete/ignore + tmp_idata(j,cid_pv) = 0 + ll = ll + 1 +! skip this i-loop + GO TO 30 + END IF + END DO +30 CONTINUE + END DO + +#ifdef DbB + IF (k>0) WRITE(*,'(A,I6,2A)') 'warning: ', k, ' & + &boundary points have been deleted, because of & + &conflicting data' +! rearange full boundary arrays +! j - "copy from" index +! i - "copy to" index + j = 1 + DO i = 1, nbc_data - k +100 IF (j<=nbc_data) THEN + IF (ibc_data(j,cbc_pv)<0) THEN +! delete boundary property "j" +! and increase "j" to the next "to be copy" position + j = j + 1 + GO TO 100 + ELSE +! fill entry for boundary point "i", copy "j" to "i" (now dense) + DO i2 = 1, nibc + ibc_data(i,i2) = ibc_data(j,i2) + END DO + DO i2 = 1, ndbc + dbc_data(i,i2,ismpl) = dbc_data(j,i2,ismpl) + END DO + j = j + 1 + END IF + END IF + END DO + nbc_data = nbc_data - k + k = 0 +! reinit first/last_<pv> + CALL sort_bc(ismpl) +#endif + IF (k>0) WRITE(*,'(A,I6,2A)') 'warning: ', k, ' & + &data have been deleted, because of conflicting & + &boundaries' + IF (ll>0) WRITE(*,'(A,I6,2A)') 'warning: ', ll, & + ' data have been deleted, because of conflicting data' + ll = ll + k + ndata = ndata - ll + + CALL alloc_data(ismpl) + + j = 0 +! *** copy ordered !!! *** + DO l = 1, npv +! l=1: copy-in HEAD elements +! 2: copy-in TEMP elements +! 3: copy-in CONC elements +! 5: copy-in PRES elements +! 6: copy-in BHPR elements + DO i = 1, ndata + ll + IF (tmp_idata(i,cid_pv)==l) THEN + j = j + 1 + DO i2 = 1, n_ddata + ddata(j,i2) = tmp_data(i,i2) + END DO + DO i2 = 1, n_idata + idata(j,i2) = tmp_idata(i,i2) + END DO + END IF + END DO + END DO +! sanity check + IF (j/=ndata) THEN + WRITE(*,'(1A,1I5,1A,1I5,1A)') 'error: lost some DATA,', & + j, '/', ndata, ', in "read_data"!!!' + STOP + END IF + +! need "ndata_p/t/c/e" before "alloc_inverse" + ndata_h = 0 + ndata_t = 0 + ndata_c = 0 + ndata_p = 0 + ndata_s = 0 + ndata_b = 0 + DO l = 1, ndata + i = idata(l,cid_i) + j = idata(l,cid_j) + k = idata(l,cid_k) + type = idata(l,cid_pv) + ozone = idata(l,cid_obs) + IF (type==pv_head) ndata_h = ndata_h + 1 + IF (type==pv_pres) ndata_p = ndata_p + 1 + IF (type==pv_temp) ndata_t = ndata_t + 1 + IF (type==pv_conc) ndata_c = ndata_c + 1 + IF (type==pv_bhpr) ndata_b = ndata_b + 1 + END DO +! sanity check + IF (ndata_h+ndata_t+ndata_c+ndata_p+ndata_s+ndata_b/=ndata) THEN + WRITE(*,'(1A,1I5,1A,1I5,1A)') 'error: lost some DATA,', & + ndata_h + ndata_t + ndata_c + ndata_p + ndata_s + ndata_b, '/', & + ndata, ', in "read_data"(2)!!!' + STOP + END IF + WRITE(*,'(1A,1I7)') & + ' [I] : data and data node adresses, records=', ndata + ELSE + WRITE(*,*) ' <D> : no observed data found, records=0' + END IF + + DEALLOCATE(tmp_idata) + DEALLOCATE(tmp_data) + +! finish HDF5 support, when available + CALL close_hdf5() + CLOSE(79) + + RETURN + +! error handler +901 WRITE(*,'(2A)') 'error: expecting "read" or a timer value', & + ' behind the keyword "timer=" !!!' + STOP +1001 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error timer i j k value-type obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1002 WRITE(*,'(2A,1I6,1A)') 'error: expecting [value error & + &timer i j k value-type species', ' obs] at line ', j, & + ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1003 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error timer i j k value-type', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1004 WRITE(*,'(2A,1I6,1A)') 'error: expecting [value error & + &timer i j k value-type species', '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1005 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error i j k value-type obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1006 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error i j k value-type species obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1007 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error i j k value-type', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +1008 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error i j k value-type species', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' cell position index: i,j,k are integer values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2001 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error timer x y z value-type obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2002 WRITE(*,'(2A,1I6,1A)') 'error: expecting [value error & + &timer x y z value-type species', ' obs] at line ', j, & + ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2003 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error timer x y z value-type', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2004 WRITE(*,'(2A,1I6,1A)') 'error: expecting [value error & + &timer x y z value-type species', '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2005 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error x y z value-type obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2006 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error x y z value-type species obs', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2007 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error x y z value-type', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP +2008 WRITE(*,'(2A,1I6,1A)') & + 'error: expecting [value error x y z value-type species', & + '] at line ', j, ' !!!' + WRITE(*,'(1A)') & + ' absolute cell position: x,y,z are floating point values' + WRITE(*,'(3A)') ' given:"', line, '"' + STOP + END diff --git a/forward/input/read_model.f90 b/forward/input/read_model.f90 new file mode 100644 index 0000000..71b0639 --- /dev/null +++ b/forward/input/read_model.f90 @@ -0,0 +1,2028 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read model parameter +!> @param[in] filename model file name +!> @param[in] ismpl local sample index +!> @details +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. + SUBROUTINE read_model(filename,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_conc + use mod_time + use mod_data + use mod_blocking_size + use mod_OMP_TOOLS + use mod_linfos +#ifndef noHDF + use mod_input_file_parser_hdf5 +#endif + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + INCLUDE 'OMP_TOOLS.inc' +! + character (len=80) :: filename + character (len=80) :: line + character (len=320) :: longline + character (len=4) :: ctmp + character (len=32) :: strng + character (len=1) :: sbc +! + DOUBLE PRECISION dtmp + DOUBLE PRECISION, ALLOCATABLE :: datmp(:,:) + LOGICAL, ALLOCATABLE :: ltmp(:,:) +! is head needed - head based computation + LOGICAL head_needed +! + INTEGER tmplen, minunits, posi, ilost +! + INTEGER ijk, omp_inner, omp_outer + INTEGER i1, i2, nbc_sections + INTEGER tracer + INTEGER sm_max +! + INTEGER locstr, lblank, read_direction, get_ioptval + EXTERNAL locstr, lblank, read_direction, get_ioptval + LOGICAL found, no_ext_link, no_ext_link_int, test_null, & + test_option + EXTERNAL found, no_ext_link, no_ext_link_int, test_null, & + test_option + logical :: found_marker + character(len=80) :: full_bc_name + + found_marker = .false. + +! + CALL read_check(filename) +! + WRITE(*,*) ' ' + WRITE(*,*) ' reading model input parameter:' + WRITE(*,*) ' from file "', filename(:lblank(filename)),'"' + WRITE(*,*) ' ' + +! ------------------ +! default sample index + ismpl = 1 + nsmpl = 1 +! generic init staff equal for all models + CALL model_init(ismpl) +! setup string constants for the number of property-units and bc-units + WRITE(c_npropunit,'(I2)') lastidx -firstidx +1 + WRITE(c_nbcunit,'(I2)') bc_lastidx -bc_firstidx +1 +! setup string constant for the number of variables + WRITE(c_npv,'(I2)') npv +! ------------------ +! read file + OPEN(79,file=filename,status='old') + +! init HDF5 support, when available + CALL open_hdf5(' ') + + title = 'NO TITLE' + IF (found(79,key_char//' title',line,.FALSE.)) THEN + READ(79,'(1A)',err=200,end=200) title + WRITE(*,*) ' [R] : title' + ELSE + WRITE(*,*) ' <D> : no title ' + END IF + + runmode = 0 + IF (found(79,key_char//' runmode',line,.FALSE.)) THEN + READ(79,*,err=202,end=202) runmode + WRITE(*,*) ' [R] : runmode' + IF (runmode==0) WRITE(*,*) ' >>> forward modeling' + IF (runmode==1) WRITE(*,*) & + ' >>> forward modeling and data fit' + IF (runmode==2) WRITE(*,*) & + ' >>> inverse modeling (extra steady state)' + IF (runmode==3) WRITE(*,*) ' >>> inverse modeling ' + ELSE + WRITE(*,*) ' <D> : runmode=0, forward modeling !' + END IF + +#ifdef DEBUG + n_debugout = 0 + CALL read_debugout(ismpl) +#endif + + write_smonitor = .FALSE. + transient = .FALSE. + + ! Default time unit [s] + tunit = tunit_const + + linfos(1) = 2 + linfos(2) = 1 + linfos(3:4) = 0 + IF (found(79,key_char//' linfo',line,.FALSE.)) THEN + READ(79,*) linfos + WRITE(*,*) ' [R] : linfo' + END IF + +#ifdef BENCH + IF (found(79,key_char//' ilu block size',line,.FALSE.)) THEN + READ(79,*) block_i,block_j,block_k + linfos(4) = -1000 + WRITE(*,*) ' [R] : ILU block size (benchmark mode)' + END IF +#endif + +! (pseudo) realisation number + sm_max = 1 + IF (found(79,key_char//' samples',line,.FALSE.)) THEN + READ(79,*,err=201,end=201) nsmpl + WRITE(*,'(1A,1I6)') ' [R] : samples =',nsmpl + END IF + sm_max = nsmpl + + IF (found(79,key_char//' PROPS',line,.FALSE.)) THEN + CALL get_arg('PROPS',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=206,end=206) def_props + ELSE + READ(line(i:j),*) def_props + END IF + ELSE + WRITE(*,'(2A)') & + 'error: can not find section "'//key_char//' PROPS=<...>",', & + ' must be defined!' + def_props = '<name>' + END IF + CALL props_check(ismpl) + + IF (found(79,key_char//' USER',line,.FALSE.)) THEN + CALL get_arg('USER',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=207,end=207) def_user + ELSE + READ(line(i:j),*) def_user + END IF + ELSE + WRITE(*,'(2A)') & + 'error: can not find section "'//key_char//' USER=<...>",', & + ' must be defined!' + def_user = '<name>' + END IF + CALL user_check(ismpl) + +! test for command line option given OpenMP parallelisation + omp_outer = 0 + omp_inner = 0 + IF (test_option('-tsample')) THEN + omp_outer = get_ioptval('-tsample') + END IF + IF (test_option('-tsolve')) THEN + omp_inner = get_ioptval('-tsolve') + END IF + IF (omp_outer>0 .AND. omp_inner>0) WRITE(*,'(2(1A,1I3),1A)') & + ' [R] : command line OpenMP thread configuration (', & + max(omp_outer,1), 'x', max(omp_inner,1), ' threads)' + IF (omp_outer==0 .AND. omp_inner>0) WRITE(*,'(2A,1I3,1A)') & + ' [R] : command line OpenMP thread configuration (', & + ' ?x', max(omp_inner,1), ' threads)' + IF (omp_outer>0 .AND. omp_inner==0) WRITE(*,'(1A,1I3,1A)') & + ' [R] : command line OpenMP thread configuration (', & + max(omp_outer,1), 'x ? threads)' + +! test for default environment given OpenMP parallelisation + IF (omp_inner>0) THEN +!$OMP parallel default(none) shared(Tlevel_0, omp_inner)& +!$OMP num_threads(omp_inner) +!$OMP master +! test thread configuartion for thread-level 0 +! (max number of sample threads) + tlevel_0 = omp_get_num_of_threads() +!$OMP end master +!$OMP end parallel + ELSE +!$OMP parallel default(none) shared(Tlevel_0) +!$OMP master +! get the number threads for thread-level 0 +! (max number of sample threads) + tlevel_0 = omp_get_num_of_threads() +!$OMP end master +!$OMP end parallel + END IF +!$OMP parallel default(none) num_threads(Tlevel_0)& +!$OMP shared(Tlevel_0,Tlevel_1,omp_inner) + IF (omp_get_his_thread_num()==0) THEN + tlevel_1 = tlevel_0 + tlevel_0 = 1 + END IF +!$OMP end parallel + +! use "sm_max" instead of "nsmpl", because of the ENKF case nsmpl = sm_max+1 + IF (omp_outer>1) WRITE(*,'(2A)') & + ' [I] : OpenMP parallelisation limited, ', & + 'target build not support nesting !' +#ifdef PROPS_IAPWS + WRITE(*,'(2A)') ' [I] : OpenMP parallelisation limited, ', & + 'IAPWS target specific behaviour.' +#endif + IF (tlevel_0>1 .OR. tlevel_1>1) WRITE(*,'(1A,1I3,1A,1I3,1A)') & + ' [I] : OpenMP parallelisation enabled (', tlevel_0, 'x', & + tlevel_1, ' threads)' + + IF (test_option('-scalemp')) THEN + CALL init_scalemp_binding() + ELSE IF (test_option('-libnuma')) THEN + CALL init_scalemp_binding() + ELSE IF (test_option('-tbind')) THEN + CALL get_coptval('-tbind',line) + CALL load_binding(line) + ELSE + CALL load_binding('default') + END IF + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + i0 = h5parse_read_dimension_size_for_dataset("grid/delx") + j0 = h5parse_read_dimension_size_for_dataset("grid/dely") + k0 = h5parse_read_dimension_size_for_dataset("grid/delz") + found_marker = .true. + else +#endif + IF (found(79,key_char//' grid',line,.FALSE.)) THEN + READ(79,*,err=203,end=203) i0, j0, k0 + found_marker = .true. + ELSE + WRITE(*,'(1A)') & + 'error: no grid dimensions i0, j0, k0 defined !' + STOP + END IF +#ifndef noHDF + endif +#endif + if (found_marker) then + found_marker = .false. + write(*,'(A,3(I4,A))') ' [R] : [i0, j0, k0] = [', i0, ',', & + j0, ',', k0, ']' + end if + + + maxiter_nl = 100 + nladapt = 0 + nlconverge = 0 + IF (found(79,key_char//' nlsolve',line,.FALSE.)) THEN + READ(79,*,err=204,end=204) maxiter_nl, nladapt + READ(79,*,err=1432,end=1432) nlconverge + GOTO 1433 +1432 nlconverge=0 +1433 WRITE(*,*) ' [R] : nonlinear solver parameter' + if (.NOT. nlconverge .eq. 0) write(*,*) ' [W] : Nonlinear Convergence test disabled!' + IF (nladapt==0) THEN + WRITE(*,*) ' [I] : fixed relxation factor assumed' + ELSE IF (nladapt==1) THEN + WRITE(*,*) ' [I] : adaptive relaxation type ', nladapt + WRITE(*,*) & + ' [E] : adaptive relaxation disabled manually!', ' & + &-> please select the fixed mode (set 0) or & + &remove this STOP!' +! Please ask Volker Rath or Andreas Wolf !!! + STOP + ELSE + WRITE(*,*) 'error: relaxation type ', nladapt, & + ' not defined' + STOP + END IF + END IF + +! --- read switches --- + IF (found(79,key_char//' active',line,.FALSE.)) THEN + head_active = .FALSE. + pres_active = .FALSE. + temp_active = .FALSE. + trac_active = .FALSE. + chem_active = .FALSE. + trans_active = .FALSE. +! test for each allowed type of calculation + i = locstr(line,'head') + IF (i>=1) THEN + head_active = .TRUE. + pres_active = .TRUE. + END IF + i = locstr(line,'pres') + IF (i>=1) THEN + pres_active = .TRUE. +#ifdef head_base + head_active = .TRUE. +#endif + END IF + i = locstr(line,'temp') + IF (i>=1) THEN + temp_active = .TRUE. + END IF + i = locstr(line,'trac') + IF (i>=1) THEN + trac_active = .TRUE. + END IF + i = locstr(line,'chem') + IF (i>=1) THEN + chem_active = .TRUE. + END IF + IF (trac_active .OR. chem_active) trans_active = .TRUE. + ELSE + head_active = .TRUE. + pres_active = .TRUE. + temp_active = .TRUE. + trac_active = .FALSE. + chem_active = .FALSE. + trans_active = .FALSE. + END IF + +! default file output compression: plain, compress_out=1 +! default file output compression: bzip2 -> "*.bz2", compress_out=2 + compress_out = 1 + IF (found(79,key_char//' file output',line,.FALSE.)) THEN + hdf_out = .FALSE. + tec_out = .FALSE. + vtk_out = .FALSE. + txt_out = .FALSE. + ctmp = ' ' + +! test for each allowed type of output files + i = locstr(line,'h5') + IF (i>=1) THEN + hdf_out = .TRUE. + ctmp(1:1) = 'X' + END IF +!- + i = locstr(line,'plt') + IF (i>=1) THEN + tec_out = .TRUE. + ctmp(2:2) = 'X' + END IF +!- + i = locstr(line,'vtk') + IF (i>=1) THEN + vtk_out = .TRUE. + ctmp(3:3) = 'X' + END IF +!- + i = locstr(line,'txt') + IF (i>=1) THEN + txt_out = .TRUE. + ctmp(4:4) = 'X' + END IF +!- may be obsolete later, use "h5" instead + i = locstr(line,'hdf') + IF (i>=1) THEN + hdf_out = .TRUE. + ctmp(1:1) = 'X' + END IF +!- may be obsolete later, use "plt" instead + i = locstr(line,'tec') + IF (i>=1) THEN + tec_out = .TRUE. + ctmp(2:2) = 'X' + END IF +!- + WRITE(*,'(1A,4(1A,1A1),1A)') ' [R] : output suffix: ', & + '.h5:[', ctmp(1:1), '], .plt:[', ctmp(2:2), '], .vtk:[', & + ctmp(3:3), '], .txt:[', ctmp(4:4), ']' + + DO j = 1, ncompress +! looking for suffix names -> enable compression tool + i = locstr(line,compress_suffix(j)) + IF (i>=1) THEN + compress_out = j + END IF + END DO + IF (compress_out>1) WRITE(*,'(3A)') & + ' [R] : output file compression enabled [*.', & + compress_suffix(compress_out), ']' + ELSE + hdf_out = .TRUE. + tec_out = .FALSE. + vtk_out = .FALSE. + txt_out = .FALSE. + END IF + + DO i = 1, nprop + out_prop(i) = .TRUE. + END DO + DO i = 1, npv + out_pv(i) = .TRUE. + END DO + DO i = 1, nout_ijk + out_ijk(i) = .TRUE. + END DO +! disable specific hdf5-outputs + IF (found(79,key_char//' disable output',line,.FALSE.)) THEN + READ(79,'(1A)',end=215) longline + CALL read_oprop(longline) + CALL read_opv(longline) + CALL read_oijk(longline) + END IF + + write_param = .TRUE. + IF (found(79,key_char//' disable small output',line,.FALSE.)) THEN +! disable the additional parameter output file + write_param = .FALSE. + END IF + + write_disable = .FALSE. + IF (found(79,key_char//' set write disable',line,.FALSE.)) THEN + write_disable = .TRUE. + write(*,'(1A)') & + ' [R] : Set write disable, write_disable = .TRUE.' + END IF + + write_iter_disable = .FALSE. + IF (found(79,key_char//' set write iter disable',line,.FALSE.)) THEN + write_iter_disable = .TRUE. + write(*,'(1A)') & + ' [R] : Set write iter disable, write_iter_disable = .TRUE.' + END IF + + read_external_input = .TRUE. + IF (found(79,key_char//' read external input',line,.FALSE.)) THEN + read(unit = 79, fmt = '(l1)') read_external_input + write(unit = *, fmt = *) ' [R] : read_external_input = ', read_external_input + END IF + +! count the number of bc-entries (sections and entries) + nbc_sections = 0 + nbc_data = 0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + do i = 1, size(pv_name) + do k = 1, size(bc_name) + j=1 + write(full_bc_name, '(A,"_",A,"_",I0)') pv_name(i), bc_name(k), j + do while (h5parse_check_dataset_exist("bc/"//full_bc_name)) + nbc_sections = nbc_sections + 1 + nbc_data = nbc_data + h5parse_read_dimension_size_for_dataset("bc/"//full_bc_name) + j = j+1 + write(full_bc_name, '(A,"_",A,"_",I0)') pv_name(i), bc_name(k), j + end do + end do + end do + else +#endif + REWIND 79 +10 READ(79,'(1A)',end=11) line + i = 0 + IF (head_active) i = i + locstr(line,key_char//' head bcd') + IF (head_active) i = i + locstr(line,key_char//' head bcn') + IF (head_active) i = i + locstr(line,key_char//' head bcw') + IF (pres_active) i = i + locstr(line,key_char//' pres bcd') + IF (pres_active) i = i + locstr(line,key_char//' pres bcn') + IF (pres_active) i = i + locstr(line,key_char//' pres bcw') + IF (temp_active) i = i + locstr(line,key_char//' temp bcd') + IF (temp_active) i = i + locstr(line,key_char//' temp bcn') + IF (trans_active) i = i + locstr(line,key_char//' conc bcd') + IF (trans_active) i = i + locstr(line,key_char//' conc bcn') +! bc line? + IF (i==1) THEN +! increase number of sections (reading later) + nbc_sections = nbc_sections + 1 + CALL get_arg('simple',line,i,j) + IF (i>=1 .AND. j>=i) THEN + k = read_direction(line(i:j)) + tmplen = 0 + IF (k==1 .OR. k==2) tmplen = j0*k0 + IF (k==3 .OR. k==4) tmplen = i0*k0 + IF (k==5 .OR. k==6) tmplen = i0*j0 + ELSE + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=205,end=205) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF + END IF +! increase number of entries + nbc_data = nbc_data + tmplen +!debug if (linfos(1).ge.2) write(*,'(1A,1I6)') +!debug & ' [I] : BC block found, but reading later, size=',tmplen + END IF +! read next line, up to the end of file + GO TO 10 +! restart file, because of the end of file here +#ifndef noHDF + end if +#endif +11 REWIND 79 +! --- end switches --- + + IF (head_active .OR. pres_active) THEN +! control environment for head/pres based computation + WRITE(*,*) ' ' + WRITE(*,*) ' reading flow parameters' + WRITE(*,*) ' ' + + aparf = 1.0D0 + IF (found(79,key_char//' lsolvef',line,.FALSE.)) THEN + READ(79,'(A)') line + CALL read_solvpar(line,errf,controlf,lmaxitf,ismpl) + WRITE(*,'(1A,1I4,1A)') & + ' [R] : flow linear solver (control=', controlf, ')' + ELSE + IF (found(79,key_char//' error lsolvef',line,.TRUE.)) THEN + READ(79,*,err=210,end=210) errf + WRITE(*,*) ' [R] : error for flow linear solver' + END IF + IF (found(79,key_char//' maxiter lsolvef',line,.TRUE.)) THEN + READ(79,*,err=211,end=211) lmaxitf + WRITE(*,*) ' [R] : max-iter for flow linear solver' + END IF + IF (found(79,key_char//' name lsolvef',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_solver(line,i,ismpl) + IF (i==-1) READ(line,*,err=212,end=212) i + WRITE(*,*) ' [R] : solver name for flow linear solver' + END IF + IF (found(79,key_char//' criteria lsolvef',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_criteria(line,j,ismpl) + IF (j==-1) READ(line,*,err=213,end=213) j + WRITE(*,*) ' [R] : criteria for flow linear solver' + END IF + IF (found(79,key_char//' precondition lsolvef',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_preco(line,k,ismpl) + IF (k==-1) READ(line,*,err=214,end=214) k + WRITE(*,*) ' [R] : precondition for flow linear solver' + END IF + CALL encntrl3(controlf,i,j,k) + END IF + + IF (found(79,key_char//' nliterf',line,.TRUE.)) THEN + dtmp = -1.0D0 + READ(79,*,err=101,end=101) nltolf, dtmp +101 WRITE(*,*) ' [R] : flow nonlinear iteration tolerance' + IF (dtmp<0.0D0) THEN + WRITE(*,'(1A)') 'error: not reading relaxation factor!' + STOP + END IF + IF (nladapt==1) THEN + nlmaxf = dtmp + WRITE(*,*) ' [I] : max flow change/iteration' + ELSE + nlrelaxf = dtmp + WRITE(*,*) ' [I] : flow nonlinear relaxation factor' + END IF + END IF + ELSE + nltolf = 1.D-30 + nltols = 1.D-30 + WRITE(*,*) ' ' + WRITE(*,*) ' <D> : no flow [disabled]' + WRITE(*,*) ' ' + END IF + + IF (temp_active) THEN + WRITE(*,*) ' ' + WRITE(*,*) ' reading heat transport parameters' + WRITE(*,*) ' ' + apart = 1.0D0 + IF (found(79,key_char//' lsolvet',line,.FALSE.)) THEN + READ(79,'(A)') line + CALL read_solvpar(line,errt,controlt,lmaxitt,ismpl) + WRITE(*,'(1A,1I4,1A)') & + ' [R] : temperature linear solver (control=', controlt,')' + ELSE + IF (found(79,key_char//' error lsolvet',line,.TRUE.)) THEN + READ(79,*,err=220,end=220) errt + WRITE(*,*) ' [R] : error for temperature linear solver' + END IF + IF (found(79,key_char//' maxiter lsolvet',line,.TRUE.)) THEN + READ(79,*,err=221,end=221) lmaxitt + WRITE(*,*) & + ' [R] : max-iter for temperature linear solver' + END IF + IF (found(79,key_char//' name lsolvet',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_solver(line,i,ismpl) + IF (i==-1) READ(line,*,err=222,end=222) i + WRITE(*,*) & + ' [R] : solver name for temperature linear solver' + END IF + IF (found(79,key_char//' criteria lsolvet',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_criteria(line,j,ismpl) + IF (j==-1) READ(line,*,err=223,end=223) j + WRITE(*,*) & + ' [R] : criteria for temperature linear solver' + END IF + IF (found(79,key_char//' precondition lsolvet',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_preco(line,k,ismpl) + IF (k==-1) READ(line,*,err=224,end=224) k + WRITE(*,*) & + ' [R] : precondition for temperature linear solver' + END IF + CALL encntrl3(controlt,i,j,k) + END IF + + IF (found(79,key_char//' nlitert',line,.TRUE.)) THEN + dtmp = -1.0D0 + READ(79,*,err=102,end=102) nltolt, dtmp +102 WRITE(*,*) & + ' [R] : temperature nonlinear iteration tolerance' + IF (dtmp<0.0D0) THEN + WRITE(*,'(1A)') 'error: not reading relaxation factor!' + STOP + END IF + IF (nladapt==1) THEN + nlmaxt = dtmp + WRITE(*,*) ' [I] : max temperature change/iteration' + ELSE + nlrelaxt = dtmp + WRITE(*,*) & + ' [I] : temperature nonlinear relaxation factor' + END IF + END IF + ELSE + nltolt = 1.D-30 + WRITE(*,*) ' ' + WRITE(*,*) ' <D> : no temperature [disabled]' + WRITE(*,*) ' ' + END IF + + ntrac = 0 + nchem = 0 + ntrans = ntrac + nchem + IF (trans_active) THEN + WRITE(*,*) ' ' + WRITE(*,*) ' reading chemical transport parameters' + WRITE(*,*) ' ' + + IF (found(79,key_char//' ntrans',line,.FALSE.)) THEN + READ(79,*,err=250,end=250) ntrac, nchem + ntrans = ntrac + nchem + WRITE(*,'(1A,2I4)') & + ' [R] : tracers, reactive components=', ntrac, nchem + ELSE + WRITE(*,*) ' <D> : no tracers or reactive components' + END IF + IF (ntrac<=0) trac_active = .FALSE. + IF (nchem<=0) chem_active = .FALSE. + trans_active = .FALSE. + IF (trac_active .OR. chem_active) trans_active = .TRUE. + END IF +! [head/pres,temp, conc...] + conv_hmax = 3 + ntrans + + IF (trans_active) THEN + aparc = 1.0D0 + IF (found(79,key_char//' lsolvec',line,.FALSE.)) THEN + READ(79,'(A)') line + CALL read_solvpar(line,errc,controlc,lmaxitc,ismpl) + WRITE(*,'(1A,1I4,1A)') & + ' [R] : transport linear solver (control=', controlc, & + ')' + ELSE + IF (found(79,key_char//' error lsolvec',line,.TRUE.)) THEN + READ(79,*,err=230,end=230) errc + WRITE(*,*) ' [R] : error for transport linear solver' + END IF + IF (found(79,key_char//' maxiter lsolvec',line,.TRUE.)) THEN + READ(79,*,err=231,end=231) lmaxitc + WRITE(*,*) & + ' [R] : max-iter for transport linear solver' + END IF + IF (found(79,key_char//' name lsolvec',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_solver(line,i,ismpl) + IF (i==-1) READ(line,*,err=232,end=232) i + WRITE(*,*) & + ' [R] : solver name for transport linear solver' + END IF + IF (found(79,key_char//' criteria lsolvec',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_criteria(line,j,ismpl) + IF (j==-1) READ(line,*,err=233,end=233) j + WRITE(*,*) & + ' [R] : criteria for transport linear solver' + END IF + IF (found(79,key_char//' precondition lsolvec',line,.TRUE.)) THEN + READ(79,'(A)') line + CALL read_preco(line,k,ismpl) + IF (k==-1) READ(line,*,err=234,end=234) k + WRITE(*,*) & + ' [R] : precondition for transport linear solver' + END IF + CALL encntrl3(controlc,i,j,k) + END IF + + IF (found(79,key_char//' nliterc',line,.TRUE.)) THEN + dtmp = -1.0D0 + READ(79,*,err=103,end=103) nltolc, dtmp +103 WRITE(*,*) & + ' [R] : transport nonlinear iteration tolerance' + IF (dtmp<0.0D0) THEN + WRITE(*,'(1A)') 'error: not reading relaxation factor!' + STOP + END IF + IF (nladapt==1) THEN + nlmaxc = dtmp + WRITE(*,*) ' [I] : max transport change/iteration' + ELSE + nlrelaxc = dtmp + WRITE(*,*) & + ' [I] : transport nonlinear relaxation factor' + END IF + END IF + ELSE + nltolc = 1.D-30 + WRITE(*,*) ' ' + WRITE(*,*) ' <D> : no transport [disabled]' + WRITE(*,*) ' ' + END IF + + + WRITE(*,*) ' ' + grav = 9.81D0 + IF (found(79,key_char//' grav',line,.FALSE.)) THEN + READ(79,*,err=251,end=251) grav + WRITE(*,'(1a,1e12.4,1a)') ' [R] : grav', grav, & + ' (>1.0d-30)' + grav = max(grav,1.D-30) + ELSE + WRITE(*,'(1a,1e12.4)') ' <D> : grav = ', grav + END IF + + hpf = 0.0D0 + IF (found(79,key_char//' hpf',line,.FALSE.)) THEN + READ(79,*,err=252,end=252) hpf + WRITE(*,*) ' [R] : hpf, fluid heat production' + ELSE + WRITE(*,*) ' <D> : no fluid heat production' + END IF + +!#ifdef head_base + IF (found(79,key_char//' rref',line,.FALSE.)) THEN + READ(79,*) rref + WRITE(*,'(1a,1e12.4)') ' [R] : rref, reference density = ' & + , rref + ELSE + rref = 998.D0 + WRITE(*,'(1a,1e12.4)') ' <D> : rref, reference density = ' & + , rref + END IF +!#endif + +! if (found(79,'? tref',line,.false.)) then +! read(79,*) tref +! write(*,'(1a,1e12.4)') +! & ' [R] : tref, referenCe temperature = ',tref +! else + tref = 20.D0 + WRITE(*,'(a,e12.4)') ' <D> : tref, reference temperature = ' & + , tref +! endif + + rhom = 2500D0 + cma1 = 1.D0 + cma2 = 0.D0 + cma3 = 0.D0 + IF (found(79,key_char//' rhocm',line,.FALSE.)) THEN + READ(79,*,err=253,end=253) rhom, cma1, cma2, cma3 + WRITE(*,*) ' [R] : rhom, rock heat capacity model' + ELSE + WRITE(*,'(1A)') ' <D> : fixed rhocm, defined by unit' + END IF +! normalise + IF (test_null(cma1)) THEN + WRITE(*,'(1A)') 'error: "cma1" equals to zero !!!' + STOP + ELSE + cma2 = cma2/cma1 + cma3 = cma3/cma1 + cma1 = 1.D0 + END IF + +! before memory allocating, counting bc-tp entries ('ngsmax') needed + ngsmax = 1 + nbctp = 0 + IF (found(79,key_char//' bc time periods',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=254,end=254) l + ELSE + READ(line(i:j),*) l + END IF + nbctp = l + DO i = 1, l +! [bctp-unit, number of entries] + READ(79,*,err=255,end=255) k, j + nbctp = max(nbctp,k) + ngsmax = max(ngsmax,j) + DO k = 1, j +! skip 'j' lines + READ(79,'(1A)') line + END DO + END DO + END IF + +! before memory allocating, counting bc-units entries ('nunits') nee + nunits = 0 + IF (found(79,key_char//' bcunits',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=256,end=256) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF + DO i = 1, tmplen + READ(79,*,err=257,end=257) k, dtmp, ctmp + nunits = max(k,nunits) + END DO + END IF + +!---------------------------------------------------------------- +! zones + WRITE(*,*) ' ' + WRITE(*,*) ' reading zone parameter ' + WRITE(*,*) ' ' + +! allocation here, because of the need for "nunits" + ALLOCATE(uindex(i0,j0,k0)) + memory = memory + i0*j0*k0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + found_marker = .true. + call h5parse_read_3d_integer_dataset("uindex", uindex) + else +#endif + IF (found(79,key_char//' uindex',line,.TRUE.)) THEN + IF (no_ext_link_int(i0,j0,k0,uindex,'uindex',line)) & + READ(79,*,err=110,end=110) (((uindex(i,j,k),i=1, & + i0),j=1,j0),k=1,k0) + found_marker = .true. + end if +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,*) ' [R] : "uindex" - unit index number, unit-cell assignment' + + maxunits = uindex(1,1,1) + minunits = uindex(1,1,1) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + maxunits = max(uindex(i,j,k),maxunits) + minunits = min(uindex(i,j,k),minunits) + END DO + END DO + END DO + + IF ((maxunits>i0*j0*k0) .OR. (minunits<1)) THEN + WRITE(*,'(A,I7,A,I7,A)') & + 'error: unit index out of range [', minunits, ',', & + maxunits, '] !' + STOP + END IF + +! also used as maximum for BC units ("bc_maxunits") + nunits = max(maxunits,nunits) + +! check thickness for each unit layer + CALL check_units(ismpl) + END IF + + nbh_logs = 0 + IF (found(79,key_char//' borehole log',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=254,end=254) nbh_logs + ELSE + READ(line(i:j),*) nbh_logs + END IF + END IF + +! ------------------ +! initialisation for linear system solver +! init array for prozessor grid, see more in 'solve/omp_preconditioniers.f' + CALL par_init2(I0,J0,K0) + +! ------------------ +! memory managment + WRITE(*,*) ' ' + CALL alloc_arrays(ismpl) + +! ------------------ +! reading later + ndata = 0 + WRITE(*,*) ' [R] : "units" - unit (rock) properties' + ALLOCATE(datmp(nprop_load,maxunits)) +! init property vaues to the default, needed when not enough values readed + DO j = 1, maxunits + DO i = 1, nprop_load + datmp(i,j) = prop_default(i) + END DO + END DO + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + j = h5parse_read_dimension_size_for_dataset("units") + call h5parse_read_2d_double_dataset("units",datmp(1:j,:)) + found_marker = .true. + else +#endif + if (found(79,key_char//' units',line,.TRUE.)) then + IF (no_ext_link(nprop_load,maxunits,1,datmp,'units',line)) & + THEN + CALL read_array(79,nprop_load,maxunits,datmp,key_char//' units', & + ismpl) + END IF + found_marker = .true. + end if +#ifndef noHDF + end if +#endif + IF (found_marker) THEN + found_marker = .false. + IF (nprop_load==lastidx-firstidx+1) THEN +! load all, dense entries (no specific index) + DO i = 1, maxunits + DO j = 1, nprop_load + propunit(i,firstidx-1+j,ismpl) = datmp(j,i) + END DO + END DO + ELSE +! needs to handle manual reading with specific index + WRITE(*,'(1A)') & + 'error: bug (1) in "read_model.f", ask AW!' + STOP + END IF + + IF (linfos(1)>=2 .AND. maxunits<=64) WRITE(*, & + '(1A18,'//c_npropunit//'(" ",1A4," "),1A6)') ' unit properties:', & + (properties(i),i=firstidx,lastidx), ' unit#' + DO i = 1, maxunits +! because of logarithimc scale, suppress zeros + propunit(i,idx_por,ismpl) = max(prop_min(idx_por), & + propunit(i,idx_por,ismpl)) + propunit(i,idx_an_kx,ismpl) = max(prop_min(idx_an_kx), & + propunit(i,idx_an_kx,ismpl)) + propunit(i,idx_an_ky,ismpl) = max(prop_min(idx_an_ky), & + propunit(i,idx_an_ky,ismpl)) + propunit(i,idx_kz,ismpl) = max(prop_min(idx_kz), & + propunit(i,idx_kz,ismpl)) +!? propunit(i,idx_comp,ismpl) = max(prop_min(idx_comp), & +!? propunit(i,idx_comp,ismpl)) + propunit(i,idx_an_lx,ismpl) = max(prop_min(idx_an_lx), & + propunit(i,idx_an_lx,ismpl)) + propunit(i,idx_an_ly,ismpl) = max(prop_min(idx_an_ly), & + propunit(i,idx_an_ly,ismpl)) + propunit(i,idx_lz,ismpl) = max(prop_min(idx_lz), & + propunit(i,idx_lz,ismpl)) + propunit(i,idx_q,ismpl) = max(prop_min(idx_q), & + propunit(i,idx_q,ismpl)) + propunit(i,idx_rc,ismpl) = max(prop_min(idx_rc), & + propunit(i,idx_rc,ismpl)) + propunit(i,idx_df,ismpl) = max(prop_min(idx_df), & + propunit(i,idx_df,ismpl)) + propunit(i,idx_ec,ismpl) = max(prop_min(idx_ec), & + propunit(i,idx_ec,ismpl)) +!? propunit(i,idx_lc,ismpl) = max(prop_min(idx_lc), & +!? propunit(i,idx_lc,ismpl)) + propunit(i,idx_s_nr,ismpl) = max(prop_min(idx_s_nr), & + propunit(i,idx_s_nr,ismpl)) + propunit(i,idx_s_wr,ismpl) = max(prop_min(idx_s_wr), & + propunit(i,idx_s_wr,ismpl)) + IF (linfos(1)>=2) WRITE(*,'(18X,'//c_npropunit//'e12.4,i6)') & + (propunit(i,j,ismpl),j=firstidx,lastidx), i + END DO + + END IF + DEALLOCATE(datmp) + +! ------------------ + + IF (nbh_logs>0) THEN + IF (found(79,key_char//' borehole log',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=254,end=254) i + ELSE + READ(line(i:j),*) i + END IF + IF (nbh_logs/=i) THEN + WRITE(*,*) 'error: more than one "borehole logs" section defined' + STOP + END IF + DO i = 1, nbh_logs +! [x-position, y-position, bh-name] + READ(79,*,err=255,end=255) ibh_pos(1,i),ibh_pos(2,i),cbh_name(i) + END DO + END IF + END IF + +! ------------------ + + WRITE(*,*) ' ' + WRITE(*,*) ' reading/preprocessing arrays' + WRITE(*,*) ' ' + + ijk = i0*j0*k0 + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + call h5parse_read_1d_double_dataset("grid/delx",delx,i0) + found_marker = .true. + else +#endif + IF (found(79,key_char//' delx',line,.TRUE.)) THEN + IF (no_ext_link(i0,1,1,delx,'delx',line)) READ(79,*, & + err=260,end=260) (delx(i),i=1,i0) + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,*) ' [R] : delx' + end if + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + call h5parse_read_1d_double_dataset("grid/dely",dely,j0) + found_marker = .true. + else +#endif + IF (found(79,key_char//' dely',line,.TRUE.)) THEN + IF (no_ext_link(1,j0,1,dely,'dely',line)) READ(79,*, & + err=261,end=261) (dely(j),j=1,j0) + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,*) ' [R] : dely' + end if +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + call h5parse_read_1d_double_dataset("grid/delz",delz,k0) + found_marker = .true. + else +#endif + IF (found(79,key_char//' delz',line,.TRUE.)) THEN + IF (no_ext_link(1,1,k0,delz,'delz',line)) READ(79,*, & + err=262,end=262) (delz(k),k=1,k0) + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,*) ' [R] : delz' + end if + +! compute absolute xyz-positions + delxa(1) = 0.5D0*delx(1) + DO i = 2, i0 + delxa(i) = delxa(i-1) + 0.5D0*(delx(i-1)+delx(i)) + END DO + delya(1) = 0.5D0*dely(1) + DO j = 2, j0 + delya(j) = delya(j-1) + 0.5D0*(dely(j-1)+dely(j)) + END DO + delza(1) = 0.5D0*delz(1) + DO k = 2, k0 + delza(k) = delza(k-1) + 0.5D0*(delz(k-1)+delz(k)) + END DO + +! initial values + WRITE(*,*) ' ' + WRITE(*,*) ' reading initial values ' + WRITE(*,*) ' ' + + head_needed = .false. +#ifdef head_base + ! Head input forced for head computation + head_needed = .true. +#endif + ! Is pres2head or head2pres needed for initial data + is_init_flow_trafo_needed = .true. + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_dataset_exist("init/head") .or. head_needed) then + call h5parse_read_3d_double_dataset("init/head", head(:,:,:,ismpl)) + found_marker = .true. + end if + else +#endif + IF (found(79,key_char//' head init',line,head_needed)) THEN + found_marker = .true. + IF (no_ext_link(i0,j0,k0,head(1,1,1, & + ismpl),'head',line)) READ(79,*,err=265,end=265) ((( & + head(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + + ! Head input for pres_base: No trafo needed + if (.not.head_needed) is_init_flow_trafo_needed = .false. + write(*,*) ' [R] : head, in [m]' + end if + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + call h5parse_read_3d_double_dataset("init/temp", temp(:,:,:,ismpl)) + else +#endif + IF (found(79,key_char//' temp init',line,.TRUE.)) THEN + IF (no_ext_link(i0,j0,k0,temp(1,1,1, & + ismpl),'temp',line)) READ(79,*,err=266,end=266) ((( & + temp(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + END IF +#ifndef noHDF + end if +#endif + WRITE(*,*) ' [R] : temp, in [degree Celsius]' + +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_dataset_exist("init/pres") .or. .not. head_needed) then + call h5parse_read_3d_double_dataset("init/pres", pres(:,:,:,ismpl)) + found_marker = .true. + end if + else +#endif + IF (found(79,key_char//' pres init',line,.NOT.head_needed)) THEN + found_marker = .true. + IF (no_ext_link(i0,j0,k0,pres(1,1,1, & + ismpl),'pres',line)) READ(79,*,err=267,end=267) ((( & + pres(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + + ! Pres input for head_base: no trafo needed + if (head_needed) is_init_flow_trafo_needed = .false. + end if + +! convert [MPa] into [Pa] + CALL dscal(i0*j0*k0,pa_conv,pres(1,1,1,ismpl),1) + WRITE(*,*) ' [R] : pres, in [MPa]' + + IF (trac_active) THEN + DO tracer = 1, ntrac + WRITE(strng,'(1A,1I4.4,1A)') key_char//' tracer', tracer, & + ' init' + CALL chln(strng,i1,i2) + IF (found(79,strng(i1:i2),line,.TRUE.)) THEN + IF (no_ext_link(i0,j0,k0,conc(1,1,1,tracer, & + ismpl),strng(i1+2:i2-5),line)) READ(79,*,err=268, & + end=268) (((conc(i,j,k,tracer,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + WRITE(*,'(1A,1I4.4,1A)') ' [R] : tracer', tracer, & + ', in [Mol/l]' + END IF + END DO + END IF + +!---------------------------------------------------------------- + +! boundary conditions if not on computional domain boundaries + WRITE(*,*) ' ' + WRITE(*,*) ' reading boundary conditions ' + WRITE(*,*) ' ' + +! initialize current number of bc-units + bc_maxunits = 0 + DO i = 1, nunits +! init undefined max values + propunit(i,idx_hbc,ismpl) = const_dble(3) + propunit(i,idx_tbc,ismpl) = const_dble(3) + propunit(i,idx_cbc,ismpl) = const_dble(3) + propunit(i,idx_snbc,ismpl) = const_dble(3) + propunit(i,idx_ebc,ismpl) = const_dble(3) + END DO + +! read the entries of irregular boundary conditions + REWIND 79 + posi = 0 + ilost = 0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + do ijk = 1, 2 + do i = 1, size(pv_name) + do k = 1, size(bc_name) + j=1 + write(full_bc_name, '(A,"_",A,"_",I0)') pv_name(i), bc_name(k), j + do while (h5parse_check_dataset_exist("bc/"//full_bc_name)) + if ((h5parse_check_attr_exist("simple", "bc/i"//full_bc_name) .and. ijk == 2) .or. & + & (.not. h5parse_check_attr_exist("simple", "bc/i"//full_bc_name) .and. ijk == 1)) then + CALL read_bc(79,full_bc_name,i,k,posi,ilost,ismpl) + end if + j = j+1 + write(full_bc_name, '(A,"_",A,"_",I0)') pv_name(i), bc_name(k), j + end do + end do + end do + end do + else +#endif + DO k = 1, nbc_sections +20 READ(79,'(1A)',err=21,end=21) line + i = 0 + j = 0 + IF (locstr(line,key_char//' head bcd')==1 .AND. head_active) THEN + i = pv_head + j = bt_diri + ELSE IF (locstr(line,key_char//' head bcn')==1 .AND. head_active) THEN + i = pv_head + j = bt_neum + ELSE IF (locstr(line,key_char//' head bcw')==1 .AND. head_active) THEN + i = pv_head + j = bt_neuw + ELSE IF (locstr(line,key_char//' pres bcd')==1 .AND. pres_active) THEN + i = pv_pres + j = bt_diri + ELSE IF (locstr(line,key_char//' pres bcn')==1 .AND. pres_active) THEN + i = pv_pres + j = bt_neum + ELSE IF (locstr(line,key_char//' pres bcw')==1 .AND. pres_active) THEN + i = pv_pres + j = bt_neuw + ELSE IF (locstr(line,key_char//' temp bcd')==1 .AND. temp_active) THEN + i = pv_temp + j = bt_diri + ELSE IF (locstr(line,key_char//' temp bcn')==1 .AND. temp_active) THEN + i = pv_temp + j = bt_neum + ELSE IF (locstr(line,key_char//' conc bcd')==1 .AND. trans_active) THEN + i = pv_conc + j = bt_diri + ELSE IF (locstr(line,key_char//' conc bcn')==1 .AND. trans_active) THEN + i = pv_conc + j = bt_neum + END IF +! bc line? + IF (i>0 .AND. j>0) THEN + CALL read_bc(79,line,i,j,posi,ilost,ismpl) + ELSE +! try next line + GO TO 20 + END IF + END DO +#ifndef noHDF + end if +#endif +! sanity check +21 IF (posi+ilost/=nbc_data) THEN + WRITE(*,'(1A)') & + 'error: lost some BC entries, in "read_model"!' + STOP + END IF +! update 'nbc_data' + nbc_data = nbc_data - ilost + +! sort "*bc_data" and setup the first/last-index for all physical va + CALL sort_bc(ismpl) + +! print out dependency betwee bc and bctp + IF (linfos(1)>=1) THEN + CALL show_bcdep(ismpl) + WRITE(*,*) ' ' + END IF +!---------------------------------------------------------------- + + IF (bc_maxunits>0) THEN + IF (found(79,key_char//' bcunits',line,.TRUE.)) THEN + + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=256,end=256) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF + +! mark the needed/used bc-units + ALLOCATE(ltmp(bc_maxunits,2)) + DO i = 1, bc_maxunits +! needed + ltmp(i,1) = .FALSE. +! used + ltmp(i,2) = .FALSE. + END DO + DO i = 1, nbc_data + k = ibc_data(i,cbc_bcu) + IF (k>0) ltmp(k,1) = .TRUE. + END DO + + IF (linfos(1)>=2) WRITE(*,'(A/2A12,A6)') & + ' bc unit properties:', ' unit# ', & + ' value ', ' type ' + DO i = 1, tmplen + READ(79,*,err=257,end=257) k, dtmp, ctmp + IF ((k>bc_maxunits) .OR. (k<1)) THEN + WRITE(*,'(2A,1I3,1A,1I3,1A)') 'error: & + &in section "bcunits", unit number & + &out of', ' range, (', k, ') at line ', i, & + ' !!!' + STOP + END IF + IF ( .NOT. ltmp(k,1)) THEN + WRITE(*,'(2A,1I3,1A,1I3,1A)') & + 'warning: in section "bcunits", unit number', & + ' not used, (', k, ') at line ', i, '.' + END IF + ltmp(k,2) = .TRUE. + IF ((ctmp/='head') .AND. (ctmp/='pres') .AND. & + (ctmp/='temp') .AND. (ctmp/='conc')) THEN + WRITE(*,'(1A,1A4,1A,1I3,1A)') 'error: & + &in section "bcunits", bc type not & + &allowed, "', ctmp, '" at line ', i, ' !!!' + STOP + END IF + +! sanity checks + IF (ctmp=='head' .AND. propunit(k,idx_hbc,ismpl)/= & + const_dble(3)) THEN + WRITE(*,'(1A,1I7,1A)') 'error: head (/ pres) bc unit ', k, & + ' multi defined !!!' + STOP + END IF + IF (ctmp=='pres' .AND. propunit(k,idx_hbc,ismpl)/= & + const_dble(3)) THEN + WRITE(*,'(1A,1I7,1A)') 'error: pres (/ head) bc unit ', k, & + ' multi defined !!!' + STOP + END IF + IF (ctmp=='temp' .AND. propunit(k,idx_tbc,ismpl)/= & + const_dble(3)) THEN + WRITE(*,'(1A,1I7,1A)') 'error: temp bc unit ', k, & + ' multi defined !!!' + STOP + END IF + IF (ctmp=='conc' .AND. propunit(k,idx_cbc,ismpl)/= & + const_dble(3)) THEN + WRITE(*,'(1A,1I7,1A)') 'error: conc bc unit ', k, & + ' multi defined !!!' + STOP + END IF +! update values + IF (ctmp=='head') propunit(k,idx_hbc,ismpl) = max(0.D0,dtmp) +! convert [MPa] into [Pa] + IF (ctmp=='pres') propunit(k,idx_hbc,ismpl) = max(0.D0,dtmp*pa_conv) + IF (ctmp=='temp') propunit(k,idx_tbc,ismpl) = dtmp + IF (ctmp=='conc') propunit(k,idx_cbc,ismpl) = max(0.D0,dtmp) + IF (linfos(1)>=2) WRITE(*,'(I11,1X,1e12.4,1X,A4)') & + k, dtmp, ctmp + END DO + WRITE(*,'(A,I7)') & + ' [R] : bc unit properties, records=', tmplen + DO k = 1, bc_maxunits + IF (ltmp(k,1) .AND. .NOT. ltmp(k,2)) THEN + WRITE(*,'(2A,1I3,1A,1I3,1A)') & + 'error: in section "bcunits", unit number', & + ' not defined, (', k, ') !!!' + STOP + END IF + END DO + DEALLOCATE(ltmp) + END IF + END IF + DO i = 1, nunits +! clear unread values + IF (propunit(i,idx_hbc,ismpl)==const_dble(3)) propunit(i,idx_hbc,ismpl) = 0.D0 + IF (propunit(i,idx_tbc,ismpl)==const_dble(3)) propunit(i,idx_tbc,ismpl) = 0.D0 + IF (propunit(i,idx_cbc,ismpl)==const_dble(3)) propunit(i,idx_cbc,ismpl) = 0.D0 + IF (propunit(i,idx_snbc,ismpl)==const_dble(3)) propunit(i,idx_snbc,ismpl) = 0.D0 + IF (propunit(i,idx_ebc,ismpl)==const_dble(3)) propunit(i,idx_ebc,ismpl) = 0.D0 + END DO + + IF (trans_active) THEN + IF (found(79,key_char//' transpar',line,.FALSE.)) THEN + DO i = 1, ntrans + READ(79,*,err=270,end=270) diff_c(i), mmas_c(i) + END DO + WRITE(*,'(1A,1I6,1A)') ' [R] : ', ntrans, & + ' diffusion constants and mol masses' + ELSE + dtmp = 1.D-9 + DO i = 1, ntrans + diff_c(i) = dtmp + mmas_c(i) = mmas_nacl + END DO + WRITE(*,*) ' <D> : uniform diffusion constant = ', & + dtmp + END IF + END IF + + + IF (found(79,key_char//' prop limit',line,.FALSE.)) THEN + WRITE(*,*) ' [R] : property limitations' + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*,err=280,end=280) tmplen + ELSE + READ(line(i:j),*) tmplen + END IF + DO i = 1, tmplen + READ(79,'(a)',err=281,end=281) line + CALL read_limit(line) + END DO + ELSE + WRITE(*,*) ' <D> : property limitations' + END IF + + IF (found(79,key_char//' velocity',line,.FALSE.)) THEN + ALLOCATE(vdefault(3,nsmpl)) + + WRITE(*,*) ' [R] : default Darcy velocity' + READ(79,*,err=282,end=282) vdefault(1,1), vdefault(2,1), vdefault(3,1) + WRITE(*,*) ' [R] : [x:vdefault(1,1), y:vdefault(2,1), z:vdefault(3,1)] = [', & + vdefault(1,1), ',', vdefault(2,1), ',', vdefault(3,1), ']' + vdefaultswitch = .true. + + DO i = 2, nsmpl + vdefault(1,i) = vdefault(1,1) + vdefault(2,i) = vdefault(2,1) + vdefault(3,i) = vdefault(3,1) + END DO + ELSE + WRITE(*,'(1A)') & + ' [R] : Zero default Darcy velocity - no # velocity!' + vdefaultswitch = .false. + END IF + +! if (found(79,key_char//' pumping',line,.false.)) then +! Call get_arg('reCords',line,i,j) +! if (i.lt.1.or.j.lt.i) then +! read(79,*) templen +! else +! read(line(i:j),*) templen +! endif +! npump=templen +! do i = 1, npump +! read(79,*) (tocell(j,i),j=1,3), (fromcell(j,i),j=1,3), howmuch(i) +! end do +! write(*,'(1A,1I6,1A)') +! & ' [R] : ',npump,' pumping/reinjeCtion setups' +! else +! write(*,*) ' <D> : no pumping/reinjeCtion setups ' +! endif + +! clean node info + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + node_info(i,j,k) = ' ' +! node_info(i,j,k)(pv_head:pv_head) = ' ' +! node_info(i,j,k)(pv_temp:pv_temp) = ' ' +! node_info(i,j,k)(pv_conc:pv_conc) = ' ' +! node_info(i,j,k)(pv_pres:pv_pres) = ' ' + END DO + END DO + END DO +! init node info + DO l = 1, nbc_data + i = ibc_data(l,cbc_i) + j = ibc_data(l,cbc_j) + k = ibc_data(l,cbc_k) + sbc = ' ' + IF (ibc_data(l,cbc_bt)==bt_diri) sbc = 'd' + IF (ibc_data(l,cbc_bt)==bt_neum) sbc = 'n' + IF (ibc_data(l,cbc_bt)==bt_neuw) sbc = 'w' + node_info(i,j,k) (ibc_data(l,cbc_pv):ibc_data(l,cbc_pv)) & + = sbc + END DO + +! ------------------ + +! finish HDF5 support, when available + CALL close_hdf5() + +! close project config file + CLOSE(79) + + RETURN + +! error handler +110 WRITE(*,'(1A,3I7,1A)') & + 'error: reading section "uindex", at index [', i, j, k, & + ']!' + STOP +200 WRITE(*,'(1A)') 'error: can not read "title"!' + STOP +201 WRITE(*,'(1A)') & + 'error: can not read number of "samples"!' + STOP +202 WRITE(*,'(1A)') 'error: can not read "runmode"!' + STOP +203 WRITE(*,'(1A)') & + 'error: can not read dimensions in section "grid"!' + STOP +204 WRITE(*,'(2A)') 'error: in section "nlsolve" expecting:', & + ' <max iter> <adapting switch = {0,1}>!' + STOP +205 WRITE(*,'(2A)') 'error: no size specified for some ', & + '"boundary condition definition"!' + STOP +206 WRITE(*,'(1A)') & + 'error: can not find section "'//key_char//' PROPS=<...>"!' + STOP +207 WRITE(*,'(1A)') & + 'error: can not find section "'//key_char//' USER=<...>"!' + STOP +210 WRITE(*,'(1A)') & + 'error: no definition for "error lsolvef"!' + STOP +211 WRITE(*,'(1A)') & + 'error: no definition for "maxiter lsolvef"!' + STOP +212 WRITE(*,'(1A)') & + 'error: no definition for "name lsolvef"!' + STOP +213 WRITE(*,'(1A)') & + 'error: no definition for "criteria lsolvef"!' + STOP +214 WRITE(*,'(1A)') & + 'error: no definition for "precondition lsolvef"!' + STOP +215 WRITE(*,'(1A)') & + 'error: file end after section "disable output"!' + STOP +220 WRITE(*,'(1A)') & + 'error: no definition for "error lsolvet"!' + STOP +221 WRITE(*,'(1A)') & + 'error: no definition for "maxiter lsolvet"!' + STOP +222 WRITE(*,'(1A)') & + 'error: no definition for "name lsolvet"!' + STOP +223 WRITE(*,'(1A)') & + 'error: no definition for "criteria lsolvet"!' + STOP +224 WRITE(*,'(1A)') & + 'error: no definition for "precondition lsolvet"!' + STOP +250 WRITE(*,'(1A)') 'error: in section "ntrans"', & + ' expecting: <#tracer> <#chemicals>!' + STOP +230 WRITE(*,'(1A)') & + 'error: no definition for "error lsolvec"!' + STOP +231 WRITE(*,'(1A)') & + 'error: no definition for "maxiter lsolvec"!' + STOP +232 WRITE(*,'(1A)') & + 'error: no definition for "name lsolvec"!' + STOP +233 WRITE(*,'(1A)') & + 'error: no definition for "criteria lsolvec"!' + STOP +234 WRITE(*,'(1A)') & + 'error: no definition for "precondition lsolvec"!' + STOP +251 WRITE(*,'(1A)') & + 'error: can not read gravity in section "grav"!' + STOP +252 WRITE(*,'(1A)') & + 'error: can not read the value in section "hpf"!' + STOP +253 WRITE(*,'(1A)') 'error: in section "rhocm"', & + 'expecting: "rhom cma1 cma2 cma3"!' + STOP +254 WRITE(*,'(1A)') & + 'error: no size specified for "bc time periods"!' + STOP +255 WRITE(*,'(2A)') 'error: in data section of "bc time periods",',& + ' expecting:',' <unit-id> <number of entries>!' + STOP +256 WRITE(*,'(1A)') 'error: no size specified for "bcunits"!' + STOP +257 WRITE(*,'(1A)') 'error: in data section of "bcunits"', & + 'please read manual!' + STOP +260 WRITE(*,'(1A)') 'error: to few values in section "delx"!' + STOP +261 WRITE(*,'(1A)') 'error: to few values in section "dely"!' + STOP +262 WRITE(*,'(1A)') 'error: to few values in section "delz"!' + STOP +265 WRITE(*,'(1A)') & + 'error: to few values in section "head init"!' + STOP +266 WRITE(*,'(1A)') & + 'error: to few values in section "temp init"!' + STOP +267 WRITE(*,'(1A)') & + 'error: to few values in section "pres init"!' + STOP +268 WRITE(*,'(1A)') & + 'error: to few values in section "tracer**** init"!' + STOP +270 WRITE(*,'(1A)') & + 'error: to few values in section "transpar"!' + STOP +280 WRITE(*,'(1A)') & + 'error: can not read number of limits in section "prop limit"!' + STOP +281 WRITE(*,'(1A)') & + 'error: to few lines in section "prop limit"!' + STOP +282 WRITE(*,'(1A)') & + 'error: wrong specification of default velocity!' + STOP + END + +!> @brief print out the dependency between bc and tpbc +!> @param[in] ismpl local sample index + SUBROUTINE show_bcdep(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + character (len=800) :: line + INTEGER i_bcu, i_bctp + +! print bc and bctp dependency + i_bcu = -1 + i_bctp = -1 + DO i = 1, nbc_data +! max bc-unit index + i_bcu = max(i_bcu,ibc_data(i,cbc_bcu)) +! max bctp index + i_bctp = max(i_bctp,ibc_data(i,cbc_bctp)) + END DO + IF (i_bcu>=0 .AND. i_bctp>=1) THEN + WRITE(*,*) ' ' + WRITE(*,'(6X,A)') 'dependency matrix [time & + &depended boundary condition]:' + WRITE(line,'(100(I8,1X))') (i,i=1,i_bctp) + WRITE(*,'(8X,1A14,1A,1A1)') '|BCunit| bctp:', & + line(1:i_bctp*11), '|' + DO i = 0, i_bcu + line = ' ' + DO j = 1, nbc_data + k = (ibc_data(j,cbc_bctp)-1)*9 + 1 + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_head .AND. & + ibc_data(j,cbc_bt)==bt_diri) line(k+1:k+2) = 'Hd' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_head .AND. & + ibc_data(j,cbc_bt)==bt_neum) line(k+1:k+2) = 'Hn' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_head .AND. & + ibc_data(j,cbc_bt)==bt_neuw) line(k+1:k+2) = 'Hw' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_pres .AND. & + ibc_data(j,cbc_bt)==bt_diri) line(k+1:k+2) = 'Pd' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_pres .AND. & + ibc_data(j,cbc_bt)==bt_neum) line(k+1:k+2) = 'Pn' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_pres .AND. & + ibc_data(j,cbc_bt)==bt_neuw) line(k+1:k+2) = 'Pw' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_temp .AND. & + ibc_data(j,cbc_bt)==bt_diri) line(k+3:k+4) = 'Td' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_temp .AND. & + ibc_data(j,cbc_bt)==bt_neum) line(k+3:k+4) = 'Tn' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_conc .AND. & + ibc_data(j,cbc_bt)==bt_diri) line(k+5:k+6) = 'Cd' + IF (ibc_data(j,cbc_bcu)==i .AND. & + ibc_data(j,cbc_bctp)>=1 .AND. & + ibc_data(j,cbc_pv)==pv_conc .AND. & + ibc_data(j,cbc_bt)==bt_neum) line(k+5:k+6) = 'Cn' + END DO + WRITE(*,'(8X,1A2,1I4,1A2,6X,1A,1A1)') '| ', i, ' |', & + line(1:i_bctp*11), '|' + END DO + END IF +! + RETURN + END + +!> @brief read all solver parameter +!> @param[in] line current character line +!> @param[out] errft break value (error) +!> @param[out] controlft solver code +!> @param[out] lmaxitft max iteration number for lin. system solver +!> @param[in] ismpl local sample index + SUBROUTINE read_solvpar(line,errft,controlft,lmaxitft,ismpl) + IMPLICIT NONE + character (len=80) :: line + DOUBLE PRECISION errft + INTEGER controlft, lmaxitft, ismpl + INTEGER i, j, c1, c2, c3, clast, beginlast + EXTERNAL clast, beginlast + + CALL read_solver(line,c1,ismpl) + CALL read_criteria(line,c2,ismpl) +! default: auto + IF (c2==-1) c2 = 4 + CALL read_preco(line,c3,ismpl) +! default: ILU + IF (c3==-1) c3 = 0 +! + IF (c1==-1) THEN + READ(line,*) errft, controlft, lmaxitft + ELSE + CALL encntrl3(controlft,c1,c2,c3) + READ(line,*) errft + j = clast(line) + i = beginlast(line(1:j)) + READ(line(i:j),*) lmaxitft + END IF +! + RETURN + END + +!> @brief read the solver type +!> @param[in] line current character line +!> @param[out] c1 linear system solver code +!> @param[in] ismpl local sample index + SUBROUTINE read_solver(line,c1,ismpl) + IMPLICIT NONE + character (len=80) :: line + INTEGER i, c1, ismpl, locstr + EXTERNAL locstr + + c1 = -1 +! check CG before BiCGStab, because CG is a substring + i = locstr(line,'cg') + IF (i>=1) c1 = 2 + i = locstr(line,'bicg') + IF (i>=1) c1 = 0 + i = locstr(line,'nag') + IF (i>=1) c1 = 1 + i = locstr(line,'plu') + IF (i>=1) c1 = 3 +! + RETURN + END + +!> @brief read the solver break criteria +!> @param[in] line current character line +!> @param[out] c2 break criteria code +!> @param[in] ismpl local sample index + SUBROUTINE read_criteria(line,c2,ismpl) + IMPLICIT NONE + character (len=80) :: line + INTEGER i, c2, ismpl, locstr + EXTERNAL locstr + + c2 = -1 + i = locstr(line,'rel') + IF (i>=1) c2 = 0 + i = locstr(line,'abs') + IF ((i>=1) .AND. (c2/=0)) c2 = 1 +! Rel + Abs + IF ((i>=1) .AND. (c2==0)) c2 = 3 + i = locstr(line,'max') + IF (i>=1) c2 = 2 + i = locstr(line,'auto') + IF (i>=1) c2 = 4 +! + RETURN + END + +!> @brief read the preconditioner type +!> @param[in] line current character line +!> @param[out] c3 preconditioner code +!> @param[in] ismpl local sample index + SUBROUTINE read_preco(line,c3,ismpl) + IMPLICIT NONE + character (len=80) :: line + INTEGER i, c3, ismpl, locstr + EXTERNAL locstr + + c3 = -1 + i = locstr(line,'ilu') + IF (i>=1) c3 = 0 + i = locstr(line,'ssor') + IF (i>=1) c3 = 1 + i = locstr(line,'diag') + IF (i>=1) c3 = 2 + i = locstr(line,'none') + IF (i>=1) c3 = 3 +! + RETURN + END + +!> @brief read the direction-type +!> @param[in] richtung direction string +!> @return direction code + INTEGER FUNCTION read_direction(richtung) + IMPLICIT NONE + character (len=*) :: richtung + INTEGER locstr + EXTERNAL locstr + + read_direction = 0 + IF (locstr(richtung,'none')==1) read_direction = 0 + IF (locstr(richtung,'0')==1) read_direction = 0 + IF (locstr(richtung,'left')==1) read_direction = 1 + IF (locstr(richtung,'1')==1) read_direction = 1 + IF (locstr(richtung,'right')==1) read_direction = 2 + IF (locstr(richtung,'2')==1) read_direction = 2 + IF (locstr(richtung,'front')==1) read_direction = 3 + IF (locstr(richtung,'3')==1) read_direction = 3 + IF (locstr(richtung,'back')==1) read_direction = 4 + IF (locstr(richtung,'4')==1) read_direction = 4 + IF (locstr(richtung,'base')==1) read_direction = 5 + IF (locstr(richtung,'5')==1) read_direction = 5 + IF (locstr(richtung,'top')==1) read_direction = 6 + IF (locstr(richtung,'6')==1) read_direction = 6 +! + RETURN + END + +#ifdef DEBUG +!> @brief debug: read additional output times +!> @param[in] ismpl local sample index + SUBROUTINE read_debugout(ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + character (len=80) :: line + INTEGER i, j, ismpl + LOGICAL found + EXTERNAL found + + IF (found(79,key_char//' debug output times',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) n_debugout + ELSE + READ(line(i:j),*) n_debugout + END IF + ALLOCATE(debugout(2,n_debugout)) + DO i = 1, n_debugout + READ(79,*) (debugout(j,i),j=1,2) + END DO + WRITE(*,'(1A,1I4)') ' [R] : debug output, records=', & + n_debugout + ELSE + WRITE(*,'(1A,1I4)') & + ' [I] : no additional debug output' +! dummy allocation + ALLOCATE(debugout(1,1)) + END IF +! + RETURN + END +#endif + +!> @brief read the property output switch +!> @param[in] line current character line + SUBROUTINE read_oprop(line) + use arrays + IMPLICIT NONE + character (len=*) :: line + INTEGER i, l, locstr, ibegin, iend + EXTERNAL locstr + + DO i = firstidx, bc_lastidx + CALL chln(properties(i),ibegin,iend) + l = locstr(line,properties(i)(ibegin:iend)) + IF (l>=1) out_prop(i) = .FALSE. + END DO +! + WRITE(*,*) ' [I] : HDF5 output configuration' + WRITE(*,'(1A,'//c_npropunit//'A5)') ' ', (properties(i),i=firstidx,lastidx) + WRITE(*,'(1A,'//c_npropunit//'L5)') ' ', (out_prop(i),i=firstidx,lastidx) +! + WRITE(*,'(1A,'//c_nbcunit//'A5)') ' ', (properties(i),i=bc_firstidx,bc_lastidx) + WRITE(*,'(1A,'//c_nbcunit//'L5)') ' ', (out_prop(i),i=bc_firstidx,bc_lastidx) +! + RETURN + END + +!> @brief read the physical-value output switch +!> @param[in] line current character line + SUBROUTINE read_opv(line) + use arrays + IMPLICIT NONE + character (len=*) :: line + INTEGER i, l, locstr, ibegin, iend + EXTERNAL locstr + + DO i = 1, npv + CALL chln(pv_name(i),ibegin,iend) + l = locstr(line,pv_name(i)(ibegin:iend)) + IF (l>=1) out_pv(i) = .FALSE. + END DO +! + WRITE(*,'(1A,'//c_npv//'A5)') ' ', (pv_name(i),i=1,npv) + WRITE(*,'(1A,'//c_npv//'L5)') ' ', (out_pv(i),i=1,npv) +! + RETURN + END + +!> @brief read the xyz-position output switch +!> @param[in] line current character line + SUBROUTINE read_oijk(line) + use arrays + IMPLICIT NONE + character (len=*) :: line + INTEGER i, l, locstr, ibegin, iend + EXTERNAL locstr + character (len=6) :: ijk_name(nout_ijk) + DATA ijk_name/' px', ' py', ' pz', ' vx', & + ' vy', ' vz', ' rhof', ' visf', 'uindex'/ + + DO i = 1, nout_ijk + CALL chln(ijk_name(i),ibegin,iend) + l = locstr(line,ijk_name(i)(ibegin:iend)) + IF (l>=1) out_ijk(i) = .FALSE. + END DO +! + WRITE(*,'(1A,9A7)') ' ', (ijk_name(i),i=1,nout_ijk) + WRITE(*,'(1A,9L7)') ' ', (out_ijk(i),i=1,nout_ijk) +! + RETURN + END + +!> @brief read property limits +!> @param[in] line current character line + SUBROUTINE read_limit(line) + USE ARRAYS + IMPLICIT NONE + character (len=*) :: line + character (len=8) :: skey + INTEGER i, j, locstr, lblank + EXTERNAL locstr, lblank + INTRINSIC adjustl, trim + +! search the parameter key-name + j = 0 + DO i = 1, nprop_load + skey = adjustl(properties(i)) + IF (locstr(line,skey(1:lblank(skey)))>=1) j = i + END DO + IF (j>=1) THEN +! MIN or MAX limitation + IF (locstr(line,'min')>=1) THEN + READ(line,*) prop_min(j) + ELSE IF (locstr(line,'max')>=1) THEN + READ(line,*) prop_max(j) + ELSE + WRITE(*,'(4A)') 'error: wrong limit specification (min|max)', & + ' in section "prop limit" line: "',trim(line),'"!' + STOP + ENDIF + ELSE + WRITE(*,'(4A)') 'error: wrong parameter keyword in section', & + ' "prop limit" line: "',trim(line),'"!' + STOP + ENDIF +! + RETURN + END diff --git a/forward/input/read_property.f90 b/forward/input/read_property.f90 new file mode 100644 index 0000000..1d0d3a3 --- /dev/null +++ b/forward/input/read_property.f90 @@ -0,0 +1,76 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read and overwrites a specific rock property (only full dimension is supported) +!> @param[in] filename "model" (or other) file name +!> @param[in] prop_idx property index number +!> @param[in] ismpl local sample index + SUBROUTINE read_property(filename,prop_idx,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE +! + INTEGER ismpl, i, j, k + character (len=80) :: filename + character (len=80) :: line + character (len=10) :: pname + INTEGER prop_idx +! + LOGICAL found, no_ext_link + EXTERNAL found, no_ext_link + INTRINSIC trim, adjustl + +! + IF (prop_idx<firstidx .OR. prop_idx>lastidx) THEN + WRITE(*,'(1A,3(1I2,1A))') 'error: property index number ',prop_idx,' out of range (',firstidx,',',lastidx,')!' + STOP + END IF +! + pname = trim(adjustl(properties(prop_idx))) + WRITE(*,*) ' [R] : '//trim(doc_properties(prop_idx))//' ('//trim(pname)//') from file "', trim(filename),'"' +! read file + OPEN(79,file=filename,status='old') +! init HDF5 support, when available + CALL open_hdf5(' ') +! + IF (found(79,key_char//' '//trim(pname),line,.TRUE.)) THEN + IF (no_ext_link(i0,j0,k0,x(1,1,1,ismpl),trim(pname),line)) & + READ(79,*,err=200,end=200) (((x(i,j,k,ismpl),i=1,i0),j=1,J0),k=1,K0) + DO k = 1, K0 + DO j = 1, J0 + DO i = 1, I0 + propunit(uindex(i,j,k),prop_idx,ismpl) = x(i,j,k,ismpl) + END DO + END DO + END DO + END IF +! +! finish HDF5 support, when available + CALL close_hdf5() +! close project config file + CLOSE(79) + RETURN + +! error handler +200 WRITE(*,'(3A)') 'error: to few values in section "',trim(pname),'"!' + STOP + END diff --git a/forward/input/read_split.f90 b/forward/input/read_split.f90 new file mode 100644 index 0000000..e1c539a --- /dev/null +++ b/forward/input/read_split.f90 @@ -0,0 +1,142 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read unit spliting +!> @param[in] filename file name +!> @param[in] ismpl local sample index +!> @details +!> read configuration for splitting some units,\n +!> split each former unit (layer) into different units for each cell\n + SUBROUTINE read_split(filename,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + character (len=80) :: filename + character (len=80) :: line + INTEGER nsplit, msplit + ! INTEGER munits + INTEGER nn + + INTEGER, ALLOCATABLE :: isplit(:), sindex(:) +! copy fields + ! INTEGER, ALLOCATABLE :: itmp(:,:) + DOUBLE PRECISION, ALLOCATABLE :: dtmp(:,:) + + INTEGER lblank + LOGICAL found + EXTERNAL lblank, found + + +! open project Config file + OPEN(79,file=filename,status='old') + + IF (found(79,key_char//' split units',line,.FALSE.)) THEN + WRITE(*,*) ' ' + WRITE(*,*) ' reading splitting parameter:' + WRITE(*,*) ' from file "', filename(:lblank(filename)), & + '"' + WRITE(*,*) ' ' + + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) nsplit + ELSE + READ(line(i:j),*) nsplit + END IF + ALLOCATE(isplit(nsplit)) + READ(79,*) (isplit(i),i=1,nsplit) + WRITE(*,'(1A,1I4,1A)') ' [I] : splitting for ', nsplit, & + ' unit(s)' + + ALLOCATE(sindex(i0*j0*k0+nunits)) + DO l = 1, nunits + sindex(l) = l + END DO +! count the number of unit-elements + msplit = nunits + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + DO l = 1, nsplit + IF (uindex(i,j,k)==isplit(l)) THEN + msplit = msplit + 1 + sindex(msplit) = uindex(i,j,k) + uindex(i,j,k) = msplit +! break the search loop + GO TO 100 + END IF + END DO +100 CONTINUE + END DO + END DO + END DO + WRITE(*,'(1A,1I9)') ' [I] : (splitted) units = ', msplit + +! # propunit + nn = nprop*nsmpl + ALLOCATE(dtmp(nunits,nn)) +! save values + CALL dcopy(nunits*nn,propunit,1,dtmp,1) +! reallocate space + DEALLOCATE(propunit) + ALLOCATE(propunit(msplit,nprop,nsmpl)) + memory = memory - nunits*nn + memory = memory + msplit*nn +! split elements, execption for "propunit", because of the bc-parts +! over all elements, normal units + DO k = 1, nsmpl + DO j = firstidx, lastidx + l = j + nprop*(k-1) + DO i = 1, msplit +! copy old values for new unit + propunit(i,j,k) = dtmp(sindex(i),l) + END DO + END DO + END DO +! over all elements, bc units + DO k = 1, nsmpl + DO j = bc_firstidx, bc_lastidx + l = j + nprop*(k-1) + DO i = 1, bc_maxunits +! copy old values for new unit + propunit(i,j,k) = dtmp(i,l) + END DO + END DO + END DO + DEALLOCATE(dtmp) + + DEALLOCATE(sindex) + DEALLOCATE(isplit) + maxunits = msplit + nunits = msplit + END IF + +! close project config file + CLOSE(79) + + RETURN + END diff --git a/forward/input/read_time.f90 b/forward/input/read_time.f90 new file mode 100644 index 0000000..6e38b80 --- /dev/null +++ b/forward/input/read_time.f90 @@ -0,0 +1,612 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read time parameter +!> @param[in] filename model file name +!> @param[in] ismpl local sample index +!> @details +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. + SUBROUTINE read_time(filename,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_conc + use mod_time + use mod_data + use mod_linfos +#ifndef noHDF + use mod_input_file_parser_hdf5 +#endif + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l +! + character (len=80) :: filename + character (len=80) :: line +! + INTEGER lblank, id, num, step_type, locstr + LOGICAL found, no_ext_link, no_ext_link_int + EXTERNAL found, no_ext_link, no_ext_link_int, lblank, locstr + + logical :: found_marker = .false. + + + WRITE(*,*) + WRITE(*,*) ' reading time input parameter:' + WRITE(*,*) ' from file "', filename(:lblank(filename)), & + '"' + WRITE(*,*) + +! read file + OPEN(79,file=filename,status='old') + +! init HDF5 support, when available + CALL open_hdf5(' ') + +! ------------------ + transient = .FALSE. + thetaf = 1.D0 + thetat = 1.D0 +! start of the simulation time + simtime(ismpl) = 0.D0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("thetaf","time")) then + call h5parse_read_double_attribute("thetaf", thetaf, "time") + call h5parse_read_double_attribute("thetat", thetat, "time") + call h5parse_read_double_attribute("thetac", thetac, "time") + call h5parse_read_double_attribute("tstart", simtime(ismpl), "time") + found_marker = .true. + end if + else +#endif + IF (found(79,key_char//' timestep control',line,.FALSE.)) THEN + READ(79,*) i + IF (i/=0) THEN + READ(79,*,err=1001) thetaf, thetat, thetac, & + simtime(ismpl) + found_marker = .true. + ELSE + WRITE(*,'(A)') ' [R] : Steady state !' + END IF + ELSE + WRITE(*,'(A)') ' <D> : Steady state !' + END IF +#ifndef noHDF + endif +#endif + if (found_marker) then + found_marker = .false. + transient = .TRUE. + WRITE(*,'(A)') ' [R] : timestep control' + IF (thetaf<0.5D0) THEN + WRITE(*,'(A)') ' theta flow < .5, set to .5!' + thetaf = 0.5D0 + END IF + IF (thetat<0.5D0) THEN + WRITE(*,'(A)') ' theta temp < .5, set to .5!' + thetat = 0.5D0 + END IF + IF (thetac<0.5D0) THEN + WRITE(*,'(A)') ' theta conc < .5, set to .5!' + thetat = 0.5D0 + END IF + END IF + + ! Default time unit [s] + tunit = tunit_const +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("tunit","time")) then + call h5parse_read_double_attribute("tunit", tunit, "time") + found_marker = .true. + end if + else +#endif + IF (found(79,key_char//' tunit',line,.FALSE.)) THEN + READ(79,*) tunit + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,'(A,1e24.8)') ' [R] : tunit =', tunit + else + WRITE(*,'(A,1e24.8,A)') ' <D> : tunit =', tunit, ' !' + end if + +! simulation start time (overwrite the reading in section "# time") +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("tstart","time")) then + found_marker = .true. + ! tstart was already read before + end if + else +#endif + IF (found(79,key_char//' tstart',line,.FALSE.)) THEN + READ(79,*) simtime(ismpl) + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,'(A,1e24.8)') ' [R] : tstart =', simtime(ismpl) + else + WRITE(*,'(A,1e24.8)') ' <D> : tstart=', simtime(ismpl) + end if + +! offset of the simulation time index + itimestep_0 = 0 +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("titer","time")) then + call h5parse_read_integer_attribute("titer", itimestep_0, "time") + found_marker = .true. + end if + else +#endif + IF (found(79,key_char//' titer',line,.FALSE.)) THEN + READ(79,*) itimestep_0 + found_marker = .true. + END IF +#ifndef noHDF + end if +#endif + if (found_marker) then + found_marker = .false. + WRITE(*,'(A,1I7)') ' [R] : titer =', itimestep_0 + else + WRITE(*,'(A,1I7)') ' <D> : titer =', itimestep_0 + end if + +! convert into sec. + simtime(ismpl) = simtime(ismpl)*tunit + simtime_0 = simtime(ismpl) + +! check for variable time step size +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_attr_exist("delt_start","time")) then + found_marker = .true. + call h5parse_read_double_attribute("delt_start", delt_start, "time") + call h5parse_read_double_attribute("delt_min", delt_min, "time") + call h5parse_read_double_attribute("delt_max", delt_max, "time") + call h5parse_read_double_attribute("max_simtime", max_simtime, "time") + call h5parse_read_integer_attribute("delt_double", delt_double, "time") + end if + else +#endif + IF (found(79,key_char//' variable step size',line,.FALSE.)) THEN + READ(79,*) i + IF (i/=0) THEN + READ(79,*,err=1002) delt_start, delt_min, delt_max, max_simtime, delt_double + found_marker = .true. + END IF + END IF +#ifndef noHDF + end if +#endif + ! Set flag for variable step size + delt_vary = found_marker + + if (found_marker) then + found_marker = .false. + WRITE(*,*) + WRITE(*,'(1A)') ' [R] : Variable time stepping: ' + WRITE(*,'(1A,1e12.4)') ' Starting step size: ', delt_start + WRITE(*,'(1A,1e12.4)') ' Minimum step size: ', delt_min + WRITE(*,'(1A,1e12.4)') ' Maximum step size: ', delt_max + WRITE(*,'(1A,1e12.4)') ' Maximum simulation time: ', max_simtime + WRITE(*,'(1A,1I7)') ' Doubling time: ', delt_double + WRITE(*,*) + end if + + ! Default number of time periods + nperiod = 0 + + ! Default total number of time steps + ntimestep = 0 + + ! Define time periods from input + IF (.not. delt_vary) THEN + + max_simtime = simtime(ismpl) +#ifndef noHDF + if (h5parse_use_hdf5_datafile) then + if (h5parse_check_dataset_exist("time/periods")) then + found_marker = .true. + nperiod = h5parse_read_dimension_size_for_dataset("time/periods") + allocate(iperiod(nperiod,2)) + call h5parse_read_2d_double_dataset("time/periods", dperiod(:nperiod,:)) + call h5parse_read_2d_integer_dataset("time/iperiods", iperiod(:nperiod,:2)) + end if + else +#endif + IF (found(79,key_char//' time periods',line,.FALSE.)) THEN + found_marker = .true. + + ! Read number of time periods + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) nperiod + ELSE + READ(line(i:j),*) nperiod + END IF + + ! Test that number of periods is a positive integer + if (nperiod < 1) then + write(unit = *, fmt = *) "[E]: Number of time periods in ", & + "'# time periods' must be positive integer.\n", & + "Input was nperiod=", nperiod + stop + end if + + allocate(iperiod(nperiod,2)) + allocate(dperiod(nperiod,2)) + + ! Read time period information + DO k = 1, nperiod +! --------------- + READ(79,'(1A)') line +! step_type : 0=not set, 1=linear, 2=logarithmic + step_type = 0 + i = locstr(line,'lin') + IF (i>=1) step_type = 1 + i = locstr(line,'log') + IF (i>=1) step_type = 2 +! JK: Logarithm + i = locstr(line,'jlo') + IF (i>=1) step_type = 3 +! increase + i = locstr(line,'inc') + IF (i>=1) step_type = abs(step_type) +! decrease + i = locstr(line,'dec') + IF (i>=1) step_type = -abs(step_type) + + ! For time period k: + ! - Read 'dperiod': [ start of time period, end of time period ] + ! - Read 'iperiod': [ # time steps, time step type] + IF (step_type==0) THEN +! need a third value as the time step type + READ(line,*,err=2001) dperiod(k,1), dperiod(k,2), & + (iperiod(k,j),j=1,2) + ELSE + READ(line,*,err=2002) dperiod(k,1), dperiod(k,2), & + (iperiod(k,j),j=1,1) + iperiod(k,2) = step_type + END IF + end do + end if +#ifndef noHDF + end if +#endif + + if (found_marker) then + WRITE(*,'(A,I4)') ' [R] : periods, records=', nperiod + found_marker = .false. + DO k = 1, nperiod + ntimestep = ntimestep + iperiod(k,1) + dperiod(k,1) = dperiod(k,1)*tunit + dperiod(k,2) = dperiod(k,2)*tunit + max_simtime = max(max_simtime,dperiod(k,2)) + + IF (iperiod(k,2)==1) THEN + WRITE(*,'(1A,1e12.4,1A,1e12.4,1A,1I8,1A)') & + ' time :', dperiod(k,1)/tunit, ' - ', & + dperiod(k,2)/tunit, ', '//key_char//' ', iperiod(k,1), ', linear' + ELSE IF (iperiod(k,2)==2) THEN + WRITE(*,'(1A,1e12.4,1A,1e12.4,1A,1I8,1A)') & + ' time :', dperiod(k,1)/tunit, ' - ', & + dperiod(k,2)/tunit, ', '//key_char//' ', iperiod(k,1), & + ', logarithmic ascending' + ELSE IF (iperiod(k,2)==3) THEN + WRITE(*,'(1A,1e12.4,1A,1e12.4,1A,1I8,1A)') & + ' time :', dperiod(k,1)/tunit, ' - ', & + dperiod(k,2)/tunit, ', '//key_char//' ', iperiod(k,1), & + ', varied logarithmic ascending' + ELSE IF (iperiod(k,2)==-2) THEN + WRITE(*,'(1A,1e12.4,1A,1e12.4,1A,1I8,1A)') & + ' time :', dperiod(k,1)/tunit, ' - ', & + dperiod(k,2)/tunit, ', '//key_char//' ', iperiod(k,1), & + ', logarithmic descending' + ELSE + WRITE(*,'(1A,1I2,1A,1I2,1A)') & + 'error: wrong time step type ', iperiod(k,2), ' at ', & + k, ' !' + STOP + END IF + + ! Sanity checks + ! ------------- + + ! start time < end time + if (dperiod(k,2) <= dperiod(k,1)) then + write(*,'(1A,1I3,1A)') & + 'error: time period START smaller then the END at ', & + k, ' !' + write(*,'(1A,1e12.4,1A,1e12.4,1A)') 't_start = ', & + dperiod(k,1)/tunit, ' > t_end = ', dperiod(k,2)/tunit, & + ' in "read_time.f" !' + stop + end if + ! no negative start / end times + if (dperiod(k,1) < 0.0d0 .or. dperiod(k,2) < 0.0d0) then + write(*,'(1A,1I4,1A)') & + 'error: no negative times allowed (period', k, & + ') in "read_time.f" !' + write(*,'(1A,1e12.4,1A,1e12.4,1A)') 't_start = ', & + dperiod(k,1)/tunit, ' < 0, or t_end', dperiod(k,2)/tunit, & + ' < 0 in "read_time.f" !' + stop + end if + ! end time = next start time + if (k>=2) then + if (1.0d0-dperiod(k-1,2)/dperiod(k,1) > 1.0d-14) then + write(*,'(1A,1I3,1A,1I3,1A)') & + 'error: time gap between period ', k - 1, ' and ', & + k, ' !' + stop + end if + if (1.0d0-dperiod(k,1)/dperiod(k-1,2) > 1.0d-14) then + write(*,'(1A,1I3,1A,1I3,1A)') & + 'error: time overlapping between period ', k - 1, & + ' and ', k, ' !' + stop + end if + ! first start time <= beginning of simulation + else if (dperiod(1,1)>simtime(ismpl)) then + write(*,'(2A)') 'error: first time period begins', & + ' later than the simulation start time !' + stop + end if + ! ------------- + + END DO + + ! Check the number of time periods + if (ntimestep < 1) then + write(unit = *, fmt = *) "Error: number of time steps (ntimestep = ", & + ntimestep, ") should be larger than zero." + stop + end if + + ! Compute time period table + CALL calc_deltatime(ismpl) + + deallocate(iperiod) + deallocate(dperiod) + + END IF + + END IF + +! read bc time periods + bctp = .FALSE. + IF (found(79,key_char//' bc time periods',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) l + ELSE + READ(line(i:j),*) l + END IF + bctp = .TRUE. +! clean counter table + DO i = 1, nbctp + ibcperiod(i) = 0 + END DO +! "bcperiod": (period-index,value-type,TP-ID,sample) +! - value-type: time, Alpha, Beta +! "ibcperiod" - number of periods: (TP-ID) +! "lbcperiod" - on/off switch: (period-index,TP-ID) + DO i = 1, l + READ(79,*,err=3000,end=3000) id, num +! sanity check + IF (num>ngsmax) THEN + WRITE(*,'(1A,1I3,1A,1I5,1A)') 'error: number of periods in "bc time periods" to big (max. ', & + ngsmax, ', ID=', id, ') !' + STOP + END IF + IF (id>nbctp) THEN + WRITE(*,'(1A)') 'error: something goes wrong with BC-TP indexing (software bug)!' + STOP + END IF +! + ibcperiod(id) = num + DO k = 1, num + READ(79,'(1A)',err=3001,end=3001) line + READ(line,*,err=3002,end=3002) (bcperiod(k,j,id,ismpl), & + j=1,3) + lbcperiod(k,id) = .TRUE. + j = locstr(line,'off') + IF (j>=1) lbcperiod(k,id) = .FALSE. + END DO + DO k = 1, num + bcperiod(k,1,id,ismpl) = tunit*bcperiod(k,1,id,ismpl) + IF (k>=2) THEN + IF (bcperiod(k,1,id,ismpl)<=bcperiod(k-1,1,id,ismpl)) & + THEN + WRITE(*,'(1A,1I2,1A,1I4,2A)') 'error: BC time period record=', i, & + ' and time changing=', k, ' has a smaller start time than before', & + ' (sorting needed)!' + STOP + END IF + END IF + END DO + END DO + WRITE(*,'(1A,1I4,1A,1I4,1A)') ' [R] : BC time periods, records=', l,' (max index =',nbctp,')' +! sanity check, full check for time period table - usage + DO i = 1, nbc_data + j = ibc_data(i,cbc_bctp) + IF (j>nbctp) THEN + WRITE(*,'(5A,1I4,1A)') 'error: "',pv_name(ibc_data(i,cbc_pv)), ' ', & + bc_name(ibc_data(i,cbc_bt)),'" time period mismatch, use of a BCTP table index ', & + j,' in the declaration, but not defined under "time periods"!' + STOP + END IF + IF (j>0) THEN + IF (ibcperiod(j)<1) THEN + WRITE(*,'(5A,1I4,1A)') 'error: "',pv_name(ibc_data(i,cbc_pv)), ' ', & + bc_name(ibc_data(i,cbc_bt)),'" time period mismatch, use of a BCTP table index ', & + j,' in the declaration, but not defined under "time periods" or zero!' + STOP + END IF + END IF + END DO + END IF + +! monitoring time steps + nmon = 0 + monitor = .FALSE. + out_orientation = 0 + IF (found(79,key_char//' monitor',line,.FALSE.)) THEN + monitor = .TRUE. + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + WRITE(*,'(1A)') & + 'error: in section "monitor", records=<number> needed!' + STOP + ELSE + READ(line(i:j),*) nmon + END IF + i = locstr(line,'col') + IF (i>=1) THEN +! column wise orientation + out_orientation = 0 + END IF + i = locstr(line,'row') + IF (i>=1) THEN +! row wise orientation + out_orientation = 1 + END IF + i = locstr(line,'new') + IF (i>=1) THEN + CALL get_arg('new',line,i,j) + IF (i>=1 .AND. j>=i) THEN +! sainty check + IF (line(i:i)=='p' .AND. out_orientation==1) THEN + WRITE(*,'(1A)') 'error: "new=position" defined, & + &but "row" not supported for it!' + STOP + END IF +! "time" defined, time named files + IF (line(i:i)=='t') out_orientation = out_orientation + & + 2 +! "position" defined, position named files + IF (line(i:i)=='p') out_orientation = out_orientation + & + 4 + ELSE +! default: time files + out_orientation = out_orientation + 2 + END IF + END IF + WRITE(*,'(A,I4,1A,1I2)') & + ' [R] : monitoring points, records=', nmon, & + ', data orientation=', out_orientation + READ(79,*,err=4001) ((imon(i,j),j=1,4),i=1,nmon) +! sanity checks + DO i = 1, nmon + IF (imon(i,1)>i0 .OR. imon(i,1)<1 .OR. imon(i,2)>j0 .OR. & + imon(i,2)<1 .OR. imon(i,3)>k0 .OR. imon(i,3)<1) THEN + WRITE(*,'(1A,1I5,1A)') 'error: monitor point ', i, & + ' out of range !' + STOP + END IF + END DO + ELSE + WRITE(*,'(1A)') ' <D> : no monitoring points !' + END IF + +! output times + noutt = 0 + IF (found(79,key_char//' output times',line,.FALSE.)) THEN + CALL get_arg('records',line,i,j) + IF (i<1 .OR. j<i) THEN + READ(79,*) noutt + ELSE + READ(line(i:j),*) noutt + END IF + DEALLOCATE(outt) + memory = memory - 1 + ALLOCATE(outt(noutt+1)) + memory = memory + noutt + 1 + IF (noutt > 0) READ(79,*) (outt(i),i=1,noutt) + DO i = 1, noutt + outt(i) = outt(i)*tunit + END DO + outt(noutt+1) = max_simtime*2.D0 +1.0d0 + WRITE(*,'(A,I4)') ' [R] : output times, records=', noutt + ELSE + outt(1) = max_simtime*2.D0 +1.0d0 + WRITE(*,'(A)') ' <D> : no output times !' + END IF + +!aw?? endif +! ------------------ + +! finish HDF5 support, when available + CALL close_hdf5() + +! close project config file + CLOSE(79) + + WRITE(*,*) + WRITE(*,*) + + RETURN + +! error handler +1001 WRITE(*,'(2A)') 'error: in section "timestep control",', & + ' awaiting [thetaf thetat thetac simtime] !' + STOP +1002 WRITE(*,'(2A)') 'error: in section "variable step size",', & + ' awaiting [delt_start, delt_min, delt_max, max_simtime, delt_double] !' + STOP +2001 WRITE(*,'(1A)') 'error: awaiting four values per line !' + STOP +2002 WRITE(*,'(1A)') 'error: awaiting three values per line !' + STOP +3000 WRITE(*,'(2A)') 'error: in section "bc time periods",', & + ' awaiting [tp-ID tp-number] !' + STOP +3001 WRITE(*,'(1A,1I3,1A)') & + 'error: awaiting BC time period information at line ', k, & + '!' + STOP +3002 WRITE(*,'(1A,1I3,1A)') 'error: awaiting three values for ', & + num, ' lines !' + STOP +4001 WRITE(*,'(1A,1I3,1A)') 'error: awaiting four values for ', & + nmon, ' lines !' + STOP + END diff --git a/forward/mathfuncs/alfa.f90 b/forward/mathfuncs/alfa.f90 new file mode 100644 index 0000000..ba83a6e --- /dev/null +++ b/forward/mathfuncs/alfa.f90 @@ -0,0 +1,48 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief truncated series expansion of cosh(x) for x < 0.1 +!> @param[in] x input value +!> @return truncated function value + double precision FUNCTION alfa(x) + IMPLICIT NONE + DOUBLE PRECISION x +! double precision x2, x3, x5, x7 + alfa = 0.D0 + IF (abs(x)>1.D-30) alfa = (x/tanh(x)-1.D0)/x + +! if (abs(x).lt.1.d-1) then +! x2 = x*x +! x3 = x2*x +! x5 = x3*x2 +! x7 = x5*x2 +! alfa = x/3.d0 - x3/4.5d1 + 2.d0*x5/9.45d2 - +! & x7/4.725d3 +! alfa = x*3.333333333333333d-01 +! & - x3*2.222222222222222d-02 +! & + x5*2.116402116402117d-03 +! & - x7*2.116402116402116e-04 +! else +! alfa=(x/tanh(x) - 1.d0)/x +! endif + RETURN + END diff --git a/forward/mathfuncs/amean.f90 b/forward/mathfuncs/amean.f90 new file mode 100644 index 0000000..8b27c06 --- /dev/null +++ b/forward/mathfuncs/amean.f90 @@ -0,0 +1,34 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the arithmetic mean between x1 and x2 +!> @param[in] x1 first value +!> @param[in] x2 second value +!> @return arithmetic mean + DOUBLE PRECISION FUNCTION amean(x1,x2) + IMPLICIT NONE + DOUBLE PRECISION x1, x2 +! + amean = 0.5D0*(x1+x2) +! + RETURN + END diff --git a/forward/mathfuncs/interpolate_lin.f90 b/forward/mathfuncs/interpolate_lin.f90 new file mode 100644 index 0000000..08706f8 --- /dev/null +++ b/forward/mathfuncs/interpolate_lin.f90 @@ -0,0 +1,125 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief inter cell interpolation +!> @param[in] I0 i-dimension +!> @param[in] J0 j-dimension +!> @param[in] K0 k-dimension +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] vals state variables (values) +!> @param[in] px I0-direction interpolation position +!> @param[in] py J0-direction interpolation position +!> @param[in] pz K0-direction interpolation position +!> @param[in] delx I0-direction cell dimensions (delta size) +!> @param[in] dely J0-direction cell dimensions (delta size) +!> @param[in] delz K0-direction cell dimensions (delta size) +!> @param[in] delxa I0-direction absolute cell positions +!> @param[in] delya J0-direction absolute cell positions +!> @param[in] delza K0-direction absolute cell positions +!> @return interpolated value + DOUBLE PRECISION FUNCTION interpolatelin(i0,j0,k0, i,j,k, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + IMPLICIT NONE +! i,j,k cell index (first corner - 3D) + INTEGER i, j, k, i0, j0, k0 +! neighbours i,j,k cell index (second corner - 3D) + INTEGER ni, nj, nk +! state variables (values) + DOUBLE PRECISION vals(i0,j0,k0) +! x,y,z cell dimensions (delta size) + DOUBLE PRECISION delx(i0), dely(j0), delz(k0) +! x,y,z absolute cell position + DOUBLE PRECISION delxa(i0), delya(j0), delza(k0) +! x,y,z interpolation position + DOUBLE PRECISION px, py, pz +! + DOUBLE PRECISION d_a0, d_b0, d_a1, d_b1, d_a2, d_b2 + DOUBLE PRECISION lin_interpol + EXTERNAL lin_interpol + INTRINSIC min, max, abs + +! get neighbour i-index + ni = i+1 + IF (px<delxa(i)) ni = i-1 + ni = min(max(ni,1),i0) +! get neighbour j-index + nj = j+1 + IF (py<delya(j)) nj = j-1 + nj = min(max(nj,1),j0) +! get neighbour k-index + nk = k+1 + IF (pz<delza(k)) nk = k-1 + nk = min(max(nk,1),k0) +! +! x1 + d_a0 = vals(i,j,k) +! x2 + d_b0 = vals(ni,j,k) +! y1 + d_a1 = lin_interpol(d_a0,d_b0,abs(delxa(i)-px),(delx(i)+delx(ni))*0.5d0) +! +! x1 + d_a0 = vals(i,nj,k) +! x2 + d_b0 = vals(ni,nj,k) +! y2 + d_b1 = lin_interpol(d_a0,d_b0,abs(delxa(i)-px),(delx(i)+delx(ni))*0.5d0) +! +! z1 + d_a2 = lin_interpol(d_a1,d_b1,abs(delya(j)-py),(dely(j)+dely(nj))*0.5d0) +! +! x1 + d_a0 = vals(i,j,nk) +! x2 + d_b0 = vals(ni,j,nk) +! y1 + d_a1 = lin_interpol(d_a0,d_b0,abs(delxa(i)-px),(delx(i)+delx(ni))*0.5d0) +! +! x1 + d_a0 = vals(i,nj,nk) +! x2 + d_b0 = vals(ni,nj,nk) +! y2 + d_b1 = lin_interpol(d_a0,d_b0,abs(delxa(i)-px),(delx(i)+delx(ni))*0.5d0) +! +! z2 + d_b2 = lin_interpol(d_a1,d_b1,abs(delya(j)-py),(dely(j)+dely(nj))*0.5d0) +! + interpolatelin = lin_interpol(d_a2,d_b2,abs(delza(k)-pz),(delz(k)+delz(nk))*0.5d0) +! + RETURN + END + +!> @brief linear interpolation +!> @param[in] da value A +!> @param[in] db value B +!> @param[in] dp relative position +!> @param[in] dd (delta) cell size +!> @return linear interpolated value + DOUBLE PRECISION FUNCTION lin_interpol(da, db, dp, dd) + IMPLICIT NONE +! da: value A; db: value B; dp: relative position; dd: (delta) cell size + DOUBLE PRECISION da, db, dp, dd + lin_interpol = (da*(dd-dp) + db*dp)/dd + RETURN + END diff --git a/forward/mathfuncs/interpolate_pol.f90 b/forward/mathfuncs/interpolate_pol.f90 new file mode 100644 index 0000000..e8a7221 --- /dev/null +++ b/forward/mathfuncs/interpolate_pol.f90 @@ -0,0 +1,290 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief inter cell interpolation +!> @param[in] I0 i-dimension +!> @param[in] J0 j-dimension +!> @param[in] K0 k-dimension +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] vals state variables (values) +!> @param[in] px I0-direction interpolation position +!> @param[in] py J0-direction interpolation position +!> @param[in] pz K0-direction interpolation position +!> @param[in] delx I0-direction cell dimensions (delta size) +!> @param[in] dely J0-direction cell dimensions (delta size) +!> @param[in] delz K0-direction cell dimensions (delta size) +!> @param[in] delxa I0-direction absolute cell position +!> @param[in] delya J0-direction absolute cell position +!> @param[in] delza K0-direction absolute cell position +!> @return interpolated value + DOUBLE PRECISION FUNCTION interpolatepol(i0,j0,k0, i,j,k, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + IMPLICIT NONE +! i,j,k cell index (first corner - 3D) + INTEGER i, j, k, i0, j0, k0, mode3d +! corrected i,j,k, can be eliminated later - px,py,pz is inside the [i,j,k] cell ([0,0,0] corner) + INTEGER c_i, c_j, c_k +! state variables (values) + DOUBLE PRECISION vals(i0,j0,k0) +! x,y,z cell dimensions (delta size) + DOUBLE PRECISION delx(i0), dely(j0), delz(k0) +! x,y,z absolute cell position + DOUBLE PRECISION delxa(i0), delya(j0), delza(k0) +! x,y,z interpolation position + DOUBLE PRECISION px, py, pz +! + DOUBLE PRECISION interpolate_3d, interpolate_am + EXTERNAL interpolate_3d, interpolate_am + INTRINSIC max, min + +! correct i-index + c_i = i + IF (px<delxa(i)) c_i = i-1 + IF (px>delxa(min(i+1,i0))) c_i = i+1 + c_i = min(max(c_i,1),i0) +! correct j-index + c_j = j + IF (py<delya(j)) c_j = j-1 + IF (py>delya(min(j+1,j0))) c_j = j+1 + c_j = min(max(c_j,1),j0) +! correct k-index + c_k = k + IF (pz<delza(k)) c_k = k-1 + IF (pz>delza(min(k+1,k0))) c_k = k+1 + c_k = min(max(c_k,1),k0) +! + mode3d = 3 + interpolatepol = interpolate_3d(i0,j0,k0, c_i,c_j,c_k, mode3d, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) +! + RETURN + END + +!> @brief inter cell interpolation (piece wise ???-methode), mode version +!> @param[in] I0 i-dimension +!> @param[in] J0 j-dimension +!> @param[in] K0 k-dimension +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] mode3d direction mode, 1==I0, 2==J0, 3==K0 +!> @param[in] vals state variables (values) +!> @param[in] px I0-direction interpolation position +!> @param[in] py J0-direction interpolation position +!> @param[in] pz K0-direction interpolation position +!> @param[in] delx I0-direction cell dimensions (delta size) +!> @param[in] dely J0-direction cell dimensions (delta size) +!> @param[in] delz K0-direction cell dimensions (delta size) +!> @param[in] delxa I0-direction absolute cell position +!> @param[in] delya J0-direction absolute cell position +!> @param[in] delza K0-direction absolute cell position +!> @return piece wise ???-methode interpolated value + DOUBLE PRECISION RECURSIVE FUNCTION interpolate_3d(i0,j0,k0, i,j,k, mode3d, vals, px,py,pz, & + delx,dely,delz, delxa,delya,delza) + IMPLICIT NONE +! i,j,k cell index (first corner - 3D) + INTEGER i, j, k, i0, j0, k0, mode3d +! state variables (values) + DOUBLE PRECISION vals(i0,j0,k0) +! x,y,z cell dimensions (delta size) + DOUBLE PRECISION delx(i0), dely(j0), delz(k0) +! x,y,z absolute cell position + DOUBLE PRECISION delxa(i0), delya(j0), delza(k0) +! x,y,z interpolation position + DOUBLE PRECISION px, py, pz +! + DOUBLE PRECISION d_a2, d_a3, d_a4, d_a5, d_d23, d_d34, d_d45, dp + DOUBLE PRECISION pw_uk_interpol, pw_cr_interpol, interpolate_3d_wrapper, lin_interpol + EXTERNAL pw_uk_interpol, pw_cr_interpol, interpolate_3d_wrapper, lin_interpol + INTRINSIC min, max + + IF (mode3d==0) THEN + interpolate_3d = vals(i,j,k) + RETURN + END IF + IF (mode3d==1) THEN +! prepare X-direction interpolation, compute directly +! cell size deltas + d_d23 = (delx(max(i-1,1))+delx(i))*0.5d0 + d_d34 = (delx(i)+delx(min(i+1,I0)))*0.5d0 + d_d45 = (delx(min(i+1,I0))+delx(min(i+2,I0)))*0.5d0 +! (x) delta + dp = px -delxa(i) +! function values + d_a2 = interpolate_3d_wrapper(i0,j0,k0, max(i-1,1),j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a3 = interpolate_3d_wrapper(i0,j0,k0, i,j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a4 = interpolate_3d_wrapper(i0,j0,k0, min(i+1,I0),j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a5 = interpolate_3d_wrapper(i0,j0,k0, min(i+2,I0),j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) +! sanity check + IF (px<delxa(i).OR.(px>delxa(min(i+1,I0)).AND.i<I0)) THEN + WRITE(*,'(1a,1i7,1a,1g16.8)') 'error: i-cell index (',i, & + ') incorrect for position :',px + STOP + END IF + END IF + IF (mode3d==2) THEN +! prepare Y-direction interpolation, consist of X-direction interpolations +! cell size deltas + d_d23 = (dely(max(j-1,1))+dely(j))*0.5d0 + d_d34 = (dely(j)+dely(min(j+1,J0)))*0.5d0 + d_d45 = (dely(min(j+1,J0))+dely(min(j+2,J0)))*0.5d0 +! (y) delta + dp = py -delya(j) +! function values + d_a2 = interpolate_3d_wrapper(i0,j0,k0, i,max(j-1,1),k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a3 = interpolate_3d_wrapper(i0,j0,k0, i,j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a4 = interpolate_3d_wrapper(i0,j0,k0, i,min(j+1,J0),k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a5 = interpolate_3d_wrapper(i0,j0,k0, i,min(j+2,J0),k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) +! sanity check + IF (py<delya(j).OR.(py>delya(min(j+1,J0)).AND.j<J0)) THEN + WRITE(*,'(1a,1i7,1a,1g16.8)') 'error: j-cell index (',j, & + ') incorrect for position :',py + STOP + END IF + END IF + IF (mode3d==3) THEN +! prepare Z-direction interpolation, consist of Y-direction interpolations +! cell size deltas + d_d23 = (delz(max(k-1,1))+delz(k))*0.5d0 + d_d34 = (delz(k)+delz(min(k+1,K0)))*0.5d0 + d_d45 = (delz(min(k+1,K0))+delz(min(k+2,K0)))*0.5d0 +! (z) delta + dp = pz -delza(k) +! function values + d_a2 = interpolate_3d_wrapper(i0,j0,k0, i,j,max(k-1,1), mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a3 = interpolate_3d_wrapper(i0,j0,k0, i,j,k, mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a4 = interpolate_3d_wrapper(i0,j0,k0, i,j,min(k+1,K0), mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + d_a5 = interpolate_3d_wrapper(i0,j0,k0, i,j,min(k+2,K0), mode3d-1, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) +! sanity check + IF (pz<delza(k).OR.(pz>delza(min(k+1,K0)).AND.k<K0)) THEN + WRITE(*,'(1a,1i7,1a,1g16.8)') 'error: k-cell index (',k, & + ') incorrect for position :',pz + STOP + END IF + END IF +! +! compute unknown-methode interpolation + interpolate_3d = pw_uk_interpol(d_a2, d_a3, d_a4, d_a5, dp, d_d23, d_d34, d_d45) +!.UNUSED/ compute Catmull-Rom interpolation +! interpolate_3d = pw_cr_interpol(d_a2, d_a3, d_a4, d_a5, dp, d_d23, d_d34, d_d45) +!.UNUSED/ compute linear interpolation +! interpolate_3d = lin_interpol(d_a3, d_a4, dp, d_d34) +! + RETURN + END + +!> @brief wrapper routine for the inter cell interpolation (piece wise ???-methode), mode version +!> @param[in] I0 i-dimension +!> @param[in] J0 j-dimension +!> @param[in] K0 k-dimension +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] mode3d direction mode, 1==I0, 2==J0, 3==K0 +!> @param[in] vals state variables (values) +!> @param[in] px I0-direction interpolation position +!> @param[in] py J0-direction interpolation position +!> @param[in] pz K0-direction interpolation position +!> @param[in] delx I0-direction cell dimensions (delta size) +!> @param[in] dely J0-direction cell dimensions (delta size) +!> @param[in] delz K0-direction cell dimensions (delta size) +!> @param[in] delxa I0-direction absolute cell position +!> @param[in] delya J0-direction absolute cell position +!> @param[in] delza K0-direction absolute cell position +!> @return piece wise ???-methode interpolated value + DOUBLE PRECISION RECURSIVE FUNCTION interpolate_3d_wrapper(i0,j0,k0, i,j,k, mode3d, vals, px,py,pz, & + delx,dely,delz, delxa,delya,delza) + IMPLICIT NONE +! i,j,k cell index (first corner - 3D) + INTEGER i, j, k, i0, j0, k0, mode3d +! state variables (values) + DOUBLE PRECISION vals(i0,j0,k0) +! x,y,z cell dimensions (delta size) + DOUBLE PRECISION delx(i0), dely(j0), delz(k0) +! x,y,z absolute cell position + DOUBLE PRECISION delxa(i0), delya(j0), delza(k0) +! x,y,z interpolation position + DOUBLE PRECISION px, py, pz +! + DOUBLE PRECISION interpolate_3d + EXTERNAL interpolate_3d + interpolate_3d_wrapper = interpolate_3d(i0,j0,k0, i,j,k, mode3d, vals, px,py,pz, delx,dely,delz, delxa,delya,delza) + RETURN + END + +!> @brief piece wise unknown-methode interpolation +!> @param[in] f_am value x_a-1 +!> @param[in] f_a value x_a +!> @param[in] f_b value x_b +!> @param[in] f_bp value x_b+1 +!> @param[in] dp relative position >= 0, for [x_a x_b] intervall, difference from x_a +!> @param[in] d_aam (delta) cell size, for [x_a-1 x_a] interval +!> @param[in] d_ba (delta) cell size, for [x_a x_b] interval +!> @param[in] d_bpb (delta) cell size, for [x_b x_b+1] interval +!> @return interpolated value + DOUBLE PRECISION FUNCTION pw_uk_interpol(f_am, f_a, f_b, f_bp, dp, d_aam, d_ba, d_bpb) + IMPLICIT NONE +! f_* function values for all nodes +! dp: relative position >= 0 +! d_* (delta) cell size, for all x_* intervals + DOUBLE PRECISION f_am, f_a, f_b, f_bp, dp, d_aam, d_ba, d_bpb + DOUBLE PRECISION ds, gf_sm, gf_xm, gf_am, gf_bm, i_s, gf_s + DOUBLE PRECISION gf_b_a + INTRINSIC max, min, dabs + LOGICAL test_null + EXTERNAL test_null + +! g_s = (2.0d0*f_b -2.0d0*f_a -gf_am*(ds-a) -gf_bm*(b-ds))/(b-a) +! ds = (g_s*(b-a) -2.0d0*f_b +2.0d0*f_a -gf_am*a +gf_bm*b) /(gf_bm -gf_am) +! mit a:=0, b:=d_ba -> +! g_s = (f_b+f_b -f_a-f_a -gf_am*ds -gf_bm*(d_ba-ds))/d_ba +! ds = (g_s*d_ba -f_b-f_b +f_a+f_a +gf_bm*d_ba) /(gf_bm -gf_am) + +! mean gradient between [a b] + gf_s = (f_b -f_a) /d_ba +! gradient mean for (a) + gf_am = 0.5d0 *((f_a -f_am) /d_aam +gf_s) +! gradient mean for (b) + gf_bm = 0.5d0 *(gf_s +(f_bp -f_b) /d_bpb) +! + gf_b_a = gf_bm -gf_am +! delta (x) sattle point + ds = 0.5d0*d_ba +! gradient for the sattle point (s) + gf_sm = 2.0d0*gf_s -0.5d0 *(gf_am +gf_bm) +! + IF (dp<ds) THEN +! gradient for (x) + gf_xm = gf_am +dp *(gf_sm -gf_am) /ds +! f_x, result for (x) + pw_uk_interpol = f_a +(gf_am +gf_xm) *dp *0.5d0 + ELSE +! integral area [a s] + i_s = (gf_sm +gf_am) *ds *0.5d0 +! gradient for (x) + gf_xm = gf_sm +(dp -ds) *(gf_bm -gf_sm) /(d_ba -ds) +! f_x, result for (x) + pw_uk_interpol = f_a +(gf_sm +gf_xm) *(dp -ds) *0.5d0 +i_s + ENDIF +! + RETURN + END diff --git a/forward/mathfuncs/mean3d.f90 b/forward/mathfuncs/mean3d.f90 new file mode 100644 index 0000000..3543723 --- /dev/null +++ b/forward/mathfuncs/mean3d.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the mean of a 3D array +!> @param[in] values 3D array +!> @param[out] meanv average value +!> @param[in] ismpl local sample index (ignored here) + SUBROUTINE mean3d(values,meanv,ismpl) + use arrays + use mod_genrl + use mod_linfos + IMPLICIT NONE + DOUBLE PRECISION meanv, values(i0,j0,k0) + integer :: i, j, k + integer :: ismpl + INTRINSIC dble + + IF (linfos(3)>=2) WRITE(*,*) ' ... mean 3D working' +! + meanv = 0.0d0 + DO k = 1, K0 + DO j = 1, J0 + DO i = 1, I0 + meanv = meanv + values(i,j,k) + END DO + END DO + END DO +! + meanv = meanv/dble(i0*j0*k0) +! + RETURN + END diff --git a/forward/mod_conc.f90 b/forward/mod_conc.f90 new file mode 100644 index 0000000..9c06f15 --- /dev/null +++ b/forward/mod_conc.f90 @@ -0,0 +1,56 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables for transport +module mod_conc + + !> @brief Number of tracers. + !> @details + !> Number of tracers. \n + !> + !> Read under `# ntrans`, first entry. + integer :: ntrac + + !> @brief Number of reactive components. + !> @details + !> Number of reactive components. \n + !> + !> Read under `# ntrans`, second entry. + integer :: nchem + + !> @brief Number of transport species. + !> @details + !> Number of transport species. \n + !> Sum of number of tracers and number of reactive components. \n + !> + !> Read under `# ntrans`, first entry. + integer :: ntrans + +! linear solver + double precision errc,aparc,nlmaxc + integer controlc,lmaxitc +! +! stopping criteria nonlinear outer loop + double precision nltolc,nlrelaxc + double precision mmas_nacl + parameter (mmas_nacl = 58.443d0) +end module mod_conc diff --git a/forward/mod_data.f90 b/forward/mod_data.f90 new file mode 100644 index 0000000..2a530b0 --- /dev/null +++ b/forward/mod_data.f90 @@ -0,0 +1,35 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables for the specification of the data +module mod_data + + !> @brief Total number of data entries. + !> @details + !> Total number of data entries. \n + !> Computed from records values of `# data` inputs. + integer :: ndata + +! temp., head., conc., pres., ???, sat_n + integer ndata_t,ndata_h,ndata_c,ndata_p,ndata_b,ndata_s + +end module mod_data diff --git a/forward/mod_flow.f90 b/forward/mod_flow.f90 new file mode 100644 index 0000000..eb0cc61 --- /dev/null +++ b/forward/mod_flow.f90 @@ -0,0 +1,102 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables for flow arrays +module mod_flow + + ! Flow: linear solver parameters + ! ------------------------------ + + !> @brief Flow linear solver error input. + !> @details + !> Flow linear solver error input. \n + !> Read under `# lsolvef`, first entry. \n\n + !> User in linear solver routines for break criteria. + double precision :: errf + + !> @brief Flow linear solver explicit/implicit switch. + !> @details + !> Flow linear solver explicit/implicit switch. \n + !> Currently set to default 1.0d0. \n\n + !> Switching capability currently disabled. + double precision :: aparf + + !> @brief Flow linear solver specification number. + !> @details + !> Flow linear solver specification number. \n + !> Read under `# lsolvef`, second entry. \n\n + !> Used in solve.f90 to specify solvername, solve criterion, + !> preconditioner. \n\n + !> + !> [ ctrl = solvername + 16*criteria + 256*precondition ] \n + !> extract [ ctrl ] : \n + !> solvername = mod(ctrl,16) \n + !> ctrl = ctrl/16 \n + !> criteria = mod(ctrl,16) \n + !> ctrl = ctrl/16 \n + !> precondition = ctrl \n\n + !> + !> Examples:\n + !> - 64: BiCGStab (parallel) solver, autodetected error, ILU + !> preconditioner + !> - 67: PLU (serial) solver, autodetected error, ILU + !> preconditioner + integer :: controlf + + !> @brief Flow linear solver maximum iteration number. + !> @details + !> Flow linear solver maximum iteration number. \n + !> Read under `# lsolvef`, third entry. \n\n + integer :: lmaxitf +! + ! stopping criteria nonlinear outer loop, head or pressure + ! -------------------------------------------------------- + + !> @brief Flow nonlinear iteration tolerance. + !> @details + !> Flow nonlinear iteration tolerance. \n + !> If the maximal difference between headold and head is smaller + !> than this tolerance, the iteration converged. + double precision :: nltolf + + !> @brief Flow nonlinear iteration relaxation. + !> @details + !> Flow nonlinear iteration relaxation. \n + double precision :: nlrelaxf + + !> @brief Flow nonlinear iteration max. + !> @details + !> Flow nonlinear iteration max. \n + !> Used in relaxation, `nl_relax`. + double precision :: nlmaxf + +! stopping criteria nonlinear outer loop, saturation + double precision nltols,nlrelaxs,nlmaxs +! constant of gravitational force, compressibility of rock + double precision grav,rref +! +! Input and Output are in [MPa], internal computation in [Pa] + double precision Pa_conv, Pa_conv1 + parameter (Pa_conv = 1.0d6) + parameter (Pa_conv1 = 1.0d0 / Pa_conv) +! +end module mod_flow diff --git a/forward/mod_genrl.f90 b/forward/mod_genrl.f90 new file mode 100644 index 0000000..29b9954 --- /dev/null +++ b/forward/mod_genrl.f90 @@ -0,0 +1,253 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief commonly used global variables and constants +module mod_genrl + + !> @brief Memory of data in 8Bytes (std. double precision size). + !> @details + !> Memory of data in 8Bytes (std. double precision size). \n + double precision memory + +! file output compression tool + integer compress_out + + !> @brief Number of cells in x-direction. + !> @details + !> Number of cells in x-direction. \n + !> Read in under `# grid`, first entry. + integer :: i0 + + !> @brief Number of cells in y-direction. + !> @details + !> Number of cells in y-direction. \n + !> Read in under `# grid`, second entry. + integer :: j0 + + !> @brief Number of cells in z-direction. + !> @details + !> Number of cells in z-direction. \n + !> Read in under `# grid`, third entry. + integer :: k0 + + !> @brief Output orientation of monitoring output. + !> @details + !> Output orientation of monitoring output. \n \n + !> `out_orientation` values: \n + !> 0: normal (pv column wise), each time step has its own block + !> (mp row wise) \n + !> 1: transposed (pv row wise), each time step has its own + !> block (mp column wise) \n + !> 2: normal (pv column wise), new file for each time step (mp + !> row wise) \n + !> 3: transposed (pv row wise), new file for each time step + !> (mp column wise) \n + !> 4: normal (pv column wise), new file for each monitor point + !> (time row wise) \n + integer :: out_orientation + + !> @brief Runmode integer. + !> @details + !> Runmode integer. \n + !> Read in under `# runmode`. \n\n + !> + !> 0: forward modeling \n + !> 1: forward modeling and data fit \n + !> 2: inverse modeling or extra steady state \n + !> 3: inverse modeling \n + integer :: runmode + + !> @brief Maximum number of nonlinear iterations. + !> @details + !> Maximum number of nonlinear iterations. \n + !> Important for the Picard iterations.\n\n + !> + !> Read under `# nlsolve`, first entry. + integer :: maxiter_nl + + integer nladapt + + !> @brief Switch for checking non-linear iteration convergence. + !> @details + !> Switch for checking non-linear iteration convergence. \n + !> - 0: check convergence (default).\n + !> - other: do not check convergence.\n + !> + !> Read under `# nlsolve`, second line, only entry. + integer nlconverge +! + logical head_active, temp_active + logical trac_active,chem_active,trans_active, pres_active + logical vtk_out,tec_out,hdf_out,txt_out + + !> @brief Switch informing if an initial flow transformation is needed. + !> @details + !> Switch informing if an initial flow transformation is needed. \n + !> This variable is .false. if the not-computed flow-variable + !> (f.e. pres in head-based computation) is given in the input + !> file. Otherwise `head2pres` or `pres2head` will be called + !> inside /forward/forward_init.f90. + logical is_init_flow_trafo_needed + + !> @brief Switch for disabling multiple outputs. + !> @details + !> Switch for disabling multiple outputs. \n + !> Disables output in write_logs, write_data, write_outt, + !> write_tecdiff, write_monitor. + logical write_disable + logical write_smonitor, write_param + + !> @brief Switch for disabling iteration output. + !> @details + !> Switch for disabling iteration output. \n + !> Disables output from forward iteration. + logical write_iter_disable + + !> @brief Switch for reading external input files. + !> @details + !> Switch for reading external input files. \n + !> If and only if read_external_input is .true., the input file + !> is searched for external input files names in the subroutine + !> read_control. + logical read_external_input + + !> @brief Hashtag character. + !> @details + !> Hashtag character. \n + !> Used as input keyword signifier. + character (len=1), parameter :: key_char = '#' + + !> @brief Number of samples. + !> @details + !> Number of samples. \n + !> For example, the number of samples in a Monte Carlo + !> simulation. Also used in OpenMP parallelization. + integer nsmpl + + ! Useful constants + ! ---------------- + + !> @brief Very big number. + !> @details + !> Very big number. \n\n + double precision, parameter :: big = 1.0d30 + + !> @brief Very small number. + !> @details + !> Very small number. \n\n + double precision, parameter :: small = 1.0d-300 + + !> @brief Circle number pi. + !> @details + !> Circle number pi. \n\n + double precision, parameter :: pi = 3.141592653589793d0 + + !> @brief Flag for log permeability output. + !> @details + !> Flag for log permeability output. \n\n + logical, parameter :: klogflag = .true. + + !> @brief Number of possible old saved arrays. + !> @details + !> Number of possible old saved arrays. \n\n + !> + !> max number of "cgen_*" + integer, parameter :: ncgen = 2 + + !> @brief Index constant for old saved arrays. + !> @details + !> Index constant for old saved arrays. \n\n + !> + !> index constants for HEAD, TEMP and PRES + !> forward iteration [x_i-1,j]; + !> do not change it without a change of any + !> "headold" into "headold(1,cgen_fw)" ccc + integer, parameter :: cgen_fw = 1 + + !> @brief Index constant for old saved arrays. + !> @details + !> Index constant for old saved arrays. \n\n + !> + !> Used around nonlinear forward iteration in `forward_iter`. + !> + !> index constants for HEAD, TEMP and PRES + !> forward iteration [x_i-1,j]; + !> do not change it without a change of any + !> "headold" into "headold(1,cgen_fw)" ccc\n\n + !> + !> time iteration + integer, parameter :: cgen_time = 2 + + ! index of the <master> sample + integer, parameter :: idx_master=1 + + !> @brief Doubling threshold for variable time step size + !> @details + !> Doubling threshold for variable time step size. \n\n + !> + !> Once delt_count reaches delt_double, the time step size is + !> doubled. \n\n + !> + !> Convergence flag, doubling value for variable time step + !> size + integer delt_double + + !> @brief Variable step size nonlinear iteration counter. + !> @details + !> Variable step size nonlinear iteration counter. \n\n + !> + !> This is a helper-counter that together with the current + !> number of iterations (in `forward_picard`) decides whether + !> the doubling counter of the variable time step size utitily + !> should be moved towards or away from doubling the time step + !> size. + integer :: iter_nlold + + !> @brief Flag for Variable step size + !> @details + !> Flag for Variable step size. \n\n + !> + !> True if variable step size is used. + logical :: delt_vary + + !> @brief Initial time step size for variable step size + !> @details + !> Initial time step size for variable step size. \n\n + !> + !> First input under `# variable step size`. + double precision :: delt_start + + !> @brief Minimum time step size for variable step size + !> @details + !> Minimum time step size for variable step size. \n\n + !> + !> Second input under `# variable step size`. + double precision :: delt_min + + !> @brief Maximum time step size for variable step size + !> @details + !> Maximum time step size for variable step size. \n\n + !> + !> Third input under `# variable step size`. + double precision :: delt_max + +end module mod_genrl diff --git a/forward/mod_genrlc.f90 b/forward/mod_genrlc.f90 new file mode 100644 index 0000000..7d17dc5 --- /dev/null +++ b/forward/mod_genrlc.f90 @@ -0,0 +1,38 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief commonly used character global variables +module mod_genrlc + character (len=80) :: title + character (len=256) :: project + + !> @brief Filename of status log output file. + !> @details + !> Filename of status log output file. \n + character (len=256) :: status_log +! +! defines the PROPS and USER choice + character (len=80) :: def_props, def_user +! +! external file control for: data + character (len=256) :: filename_data +end module mod_genrlc diff --git a/forward/mod_linfos.f90 b/forward/mod_linfos.f90 new file mode 100644 index 0000000..bdac57b --- /dev/null +++ b/forward/mod_linfos.f90 @@ -0,0 +1,53 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief info, verbosity level +module mod_linfos + + !> @brief Array of verbosity level switches. + !> @details + !> Array of verbosity level switches. \n\n + !> linfos(1)=\n + !> - `0`, only necessary outputs\n + !> - `1`, time steps information\n + !> - `2`, with initialisation and file reading outputs\n + !> + !> linfos(2)=\n + !> - `0`, 'inversion/simulation' with only necessary outputs\n + !> - `1`, 'inversion/simulation' with some more outputs\n + !> - `2`, 'inversion/simulation' with all outputs (optimisation outputs)\n + !> - `3`, 'inversion/simulation' with all debug outputs\n + !> + !> linfos(3)=\n + !> - `-1`, 'non linear solver' disables some error outputs\n + !> - `0`, 'non linear solver' with only necessary outputs\n + !> - `1`, 'non linear solver' with some stage outputs\n + !> - `2`, 'non linear solver' with all outputs\n + !> + !> linfos(4)=\n + !> - `0`, 'system solver' without any outputs\n + !> - `1`, 'system solver' with some outputs\n + !> - `2`, 'system solver' with some debug outputs\n + !> - `3`, 'system solver' with all debug outputs\n + integer, dimension (4) :: linfos + +end module mod_linfos diff --git a/forward/mod_temp.f90 b/forward/mod_temp.f90 new file mode 100644 index 0000000..26236c3 --- /dev/null +++ b/forward/mod_temp.f90 @@ -0,0 +1,34 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables for heat transport +module mod_temp +! linear solver + integer controlt,lmaxitt + double precision errt,apart +! +! stopping criteria nonlinear outer loop + double precision nltolt,nlrelaxt,nlmaxt +! +! rock heat capacity, density ,conductivity + double precision cma1,cma2,cma3,rhom,tref,hpf +end module mod_temp diff --git a/forward/mod_time.f90 b/forward/mod_time.f90 new file mode 100644 index 0000000..81dbcd3 --- /dev/null +++ b/forward/mod_time.f90 @@ -0,0 +1,172 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables for timestepping +module mod_time + + !> @brief Time unit factor. + !> @details + !> Time unit factor. \n + !> Default: 1.0d0. \n\n + !> + !> Read in under keyword `# tunit`. \n\n + !> + !> All time inputs are multiplied by this factor. Since the + !> general computation expects seconds, the following + !> correspondences hold: \n + !> - tunit = 1.0d0: unit [s] \n + !> - tunit = 60.0d0: unit [min] \n + !> - tunit = 3600.0d0: unit [h] \n + !> - tunit = 86400.0d0: unit [day] \n + !> - tunit = 31536000.0d0: unit [a] with 365 days per year \n + double precision :: tunit + + !> @brief Default time unit factor. + !> @details + !> Default time unit factor. \n + !> Corresponds to time unit [s], seconds. \n\n + double precision, parameter :: tunit_const = 1.0d0 + + !> @brief Transient computation switch. + !> @details + !> Transient computation switch. \n + !> `.true.`: transient computation. \n + !> `.false.`: steady state computation. + logical transient + + !> @brief Maximum number of time periods. + !> @details + !> Maximum number of time periods. \n + integer, parameter :: npermax = 1056 + + !> @brief Maximum simulation time. + !> @details + !> Maximum simulation time. \n\n + !> + !> Read under `# time periods`. Set to the end time of the + !> last time period. + double precision max_simtime + + !> @brief Start of simulation time. + !> @details + !> Start of simulation time. \n\n + !> + !> Read under `# timestep control` (second line, fourth entry) + !> or under `# tstart`. + !> + !> "simtime_0" is needed for inverse-restart + double precision simtime_0 + + !> @brief Total number of time steps. + !> @details + !> Total number of time steps. \n + !> Default: 0. \n\n + !> + !> If `# time periods` is read, the number of time steps is + !> recorded in this variable. For variable time step size, the + !> value of ntimestep is zero. + integer ntimestep + + !> @brief Initial time step index. + !> @details + !> Initial time step index. \n + !> The initial time step index. Default: 0. \n\n + !> + !> For forward runs, itimestep_0 will set an offset in the time + !> index. A simulation of 100 time steps, will then run from + !> `itimestep_0` to `100+itimestep_0`. Otherwise, the + !> time-handling will be equivalent.\n\n + !> + !> Read in under `# titer`. \n\n + !> + !> "itimestep_0" is needed for inverse-restart. + integer itimestep_0 + + !> @brief Number of time periods. + !> @details + !> Number of time periods. \n + !> The number of time periods is not used if variable time step + !> size is defined. + integer :: nperiod + + !> @brief Time period specification array. + !> @details + !> Time period specification array. \n + !> - iperiod(ip,1): number of time steps of period ip \n + !> - iperiod(ip,2): time step size of period ip \n\n + !> + !> time step type: 1=linear, 2=logarithmic, 3=jlo (logarithmic + !> variation), -2= logarithmic decreasing + integer, allocatable, dimension (:,:) :: iperiod + + !> @brief Time period start and end array. + !> @details + !> Time period start and end array. \n + !> - dperiod(ip,1): starting time of period ip \n + !> - dperiod(ip,2): ending time of period ip \n\n + !> + !> Start and end time of the time period are given in time unit + !> `tunit`, and then converted into seconds for the rest of the + !> computation. \n + double precision, allocatable, dimension (:,:) :: dperiod + + !> @brief Static relaxation for flow. + !> @details + !> Static relaxation for flow. \n + !> + !> Read under `# timestep control`, first entry. + double precision :: thetaf + + !> @brief Static relaxation for temperature. + !> @details + !> Static relaxation for temperature. \n + !> + !> Read under `# timestep control`, second entry. + double precision :: thetat + + !> @brief Static relaxation for concentration. + !> @details + !> Static relaxation for concentration. \n + !> + !> Read under `# timestep control`, third entry. + double precision :: thetac +! + logical bctp +! number of bc-tp entries + integer ngsmax + integer ngststep, nbctp +! + + !> @brief Switch for monitor output. + !> @details + !> Switch for monitor output. \n\n + logical :: monitor + + integer nmon,imon(npermax,4) + + !> @brief Number of output times. + !> @details + !> Number of output times. \n + !> Records entry under `# output times`. + integer noutt + +end module mod_time diff --git a/forward/model_init.f90 b/forward/model_init.f90 new file mode 100644 index 0000000..71374e6 --- /dev/null +++ b/forward/model_init.f90 @@ -0,0 +1,75 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief inititialise cache/block size +!> @details +!> initialise cache size and block parameters\n +!> and numerical basis constants (zero values, precision ...)\n + SUBROUTINE model_init(ismpl) + USE arrays + use mod_genrl + use mod_blocking_size + IMPLICIT NONE + integer :: ismpl + DOUBLE PRECISION dlamch + EXTERNAL dlamch + INTRINSIC dsqrt + +! !! defines lin. solver constants [part 1] !! + bldiv_cg = 7.0D0 + bldiv_bicg(1) = 10.5D0 + bldiv_bicg(2) = 5.5D0 + bldiv_mvp = 11.5D0 + bldiv_dot(1) = 2.0D0 + bldiv_dot(2) = 6.5D0 + bldiv_dot(3) = 8.0D0 +! +! !! defines lin. solver constants [part 2] !! +#ifdef CLsun +! cache size for SUN Ultra-Sparc-III (8 MByte) cpu + cache_size = 384000 +#elif CLopt +! cache size for AMD Opteron (1 MByte) cpu + cache_size = 1024000 +#elif CLpen +! cache size for Intel P4 (512 KByte) cpu + cache_size = 512000 +#else +! cache size for Intel P4/Celeron (128 KByte) cpu + cache_size = 128000 +#endif +! block size (number of doubles minus 20%) + bl_size = cache_size / 10 + +! initalise some values + memory = 0.0D0 + + const_dble(1) = dlamch('E') +! 3/4 of the min value + const_dble(2) = dsqrt(dlamch('U')) + const_dble(2) = const_dble(2)*dsqrt(const_dble(2)) +! 3/4 of the max value + const_dble(3) = dsqrt(dlamch('O')) + const_dble(3) = const_dble(3)*dsqrt(const_dble(3)) + + RETURN + END diff --git a/forward/nlrelaxad.f90 b/forward/nlrelaxad.f90 new file mode 100644 index 0000000..8914776 --- /dev/null +++ b/forward/nlrelaxad.f90 @@ -0,0 +1,68 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief adaptive relaxation parameter +!> @param[in] iter iteration counter +!> @param[in] r <description> +!> @param[in] rold <description> +!> @param[in] emax <description> +!> @param[out] relax current relaxation value +!> @param[in,out] relaxold old relaxation value +!> @param[in] ismpl local sample index +!> @details +!> calculate adaptive relaxation parameter\n +!> see Cooley (1983), WRR 19(5), 1271-1285\n + SUBROUTINE nl_relax(iter,r,rold,emax,relax,relaxold,ismpl) + use mod_genrl + use mod_genrlc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + INTEGER iter + DOUBLE PRECISION r, rold, emax, relax, relaxold, s + +! step 1 + IF (iter==1) THEN + s = 1.0D0 + ELSE + s = r/(relaxold*rold) + END IF + WRITE(*,*) 'r, rold =', r, rold, ' s= ', s +! step 2 + IF (s>=-1.D0) THEN + relax = (3.D0+s)/(3.D0+abs(s)) + ELSE + relax = 0.5D0/abs(s) + END IF +! step 3 + IF (relax*abs(r)>emax) relax = emax/abs(r) + relax = min(1.D0,max(0.05D0,relax)) + WRITE(*,*) '**** relax= ', relax, ' (', relaxold, ')' +! + relaxold = relax +! + IF (linfos(3)>=1) THEN + WRITE(*,'(1a,1e10.3)') ' relaxation factor: ', relax + END IF +! + RETURN + END diff --git a/forward/no_ext_link.f90 b/forward/no_ext_link.f90 new file mode 100644 index 0000000..fffbb4e --- /dev/null +++ b/forward/no_ext_link.f90 @@ -0,0 +1,208 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief extract extern file name and read the double precision array 'A' +!> @param[in] NI i-direction array dimension +!> @param[in] NJ j-direction array dimension +!> @param[in] NK k-direction array dimension +!> @param[in] A_name array name (ascii) +!> @param[in] name_link line for extracting +!> @param[out] A array with all data +!> @return "true" it was not an external file, FALSE: data from external file readed + LOGICAL FUNCTION no_ext_link(ni,nj,nk,a,a_name,name_link) + use mod_genrlc + IMPLICIT NONE + INTEGER i1, i2 + character (len=80) :: defaultname +! arrayname and filename + character (len=*) :: a_name +! + INTEGER ni, nj, nk + INTEGER j, k + DOUBLE PRECISION a(ni,nj,nk) +! + character (len=*) :: name_link +! + INTEGER sfirst, end_sec + EXTERNAL sfirst +! + LOGICAL is_txt + +! default HDF5 input file name + CALL chln(project,i1,i2) +! + is_txt = .FALSE. + CALL get_arg('HDF5',name_link,j,k) + defaultname = project(i1:i2) // '.h5' + IF (j<1 .OR. k<j) THEN + is_txt = .TRUE. + CALL get_arg('TXT',name_link,j,k) + defaultname = project(i1:i2) // '.txt' + IF (j<1 .OR. k<j) THEN + no_ext_link = .TRUE. + RETURN + END IF + END IF +! end of the section name + end_sec = sfirst(name_link) +! +! found extern file declaration + IF (name_link(j:k)=='default') THEN + IF (is_txt) THEN + CALL read_open_txt(ni,nj,nk,a,name_link(1:end_sec), & + defaultname) + ELSE + CALL read_hdf5(ni,nj,nk,a,a_name,defaultname) + END IF + ELSE + IF (is_txt) THEN + CALL read_open_txt(ni,nj,nk,a,name_link(1:end_sec), & + name_link(j:k)) + ELSE + CALL read_hdf5(ni,nj,nk,a,a_name,name_link(j:k)) + END IF + END IF + no_ext_link = .FALSE. +! + RETURN + END + +!> @brief extract extern file name and read the integer array 'A' +!> @param[in] NI i-direction array dimension +!> @param[in] NJ j-direction array dimension +!> @param[in] NK k-direction array dimension +!> @param[in] A_name array name (ascii) +!> @param[in] name_link line for extracting +!> @param[out] A array with all data +!> @return "true" it was not an external file, FALSE: data from external file readed + LOGICAL FUNCTION no_ext_link_int(ni,nj,nk,a,a_name,name_link) + use mod_genrlc + IMPLICIT NONE + INTEGER i1, i2 + character (len=80) :: defaultname +! arrayname and filename + character (len=*) :: a_name +! + INTEGER ni, nj, nk + INTEGER j, k + INTEGER a(ni,nj,nk) +! + character (len=*) :: name_link +! + INTEGER sfirst, end_sec + EXTERNAL sfirst +! + LOGICAL is_txt + +! default HDF5 input file name + CALL chln(project,i1,i2) + defaultname = project(i1:i2) // '.h5' +! + is_txt = .FALSE. + CALL get_arg('HDF5',name_link,j,k) + IF (j<1 .OR. k<j) THEN + is_txt = .TRUE. + CALL get_arg('TXT',name_link,j,k) + IF (j<1 .OR. k<j) THEN + no_ext_link_int = .TRUE. + RETURN + END IF + END IF +! end of the section name + end_sec = sfirst(name_link) +! +! found extern file declaration + IF (name_link(j:k)=='default') THEN + IF (is_txt) THEN + CALL read_open_txt_int(ni,nj,nk,a,name_link(1:end_sec), & + defaultname) + ELSE + CALL read_hdf5_int(ni,nj,nk,a,a_name,defaultname) + END IF + ELSE + IF (is_txt) THEN + CALL read_open_txt_int(ni,nj,nk,a,name_link(1:end_sec), & + name_link(j:k)) + ELSE + CALL read_hdf5_int(ni,nj,nk,a,a_name,name_link(j:k)) + END IF + END IF + no_ext_link_int = .FALSE. +! + RETURN + END + +!> @brief read double precision data from file +!> @param[in] NI i-direction array dimension +!> @param[in] NJ j-direction array dimension +!> @param[in] NK k-direction array dimension +!> @param[in] A_name array name (ascii) +!> @param[in] f_name file name +!> @param[out] A array with all data + SUBROUTINE read_open_txt(ni,nj,nk,a,a_name,f_name) + IMPLICIT NONE + character (len=*) :: a_name, f_name + character (len=80) :: line + INTEGER ni, nj, nk, i, j, k + DOUBLE PRECISION a(ni,nj,nk) + LOGICAL found + EXTERNAL found + + WRITE(*,*) ' open TXT file: ', f_name + OPEN(89,file=f_name,status='old',err=99) + IF (found(89,a_name,line,.TRUE.)) THEN + READ(89,*) (((a(i,j,k),i=1,ni),j=1,nj),k=1,nk) + END IF + CLOSE(89) + RETURN +! +99 WRITE(*,*) 'error: can not open file "', f_name, '" !' + STOP + END + +!> @brief read integer data from file +!> @param[in] NI i-direction array dimension +!> @param[in] NJ j-direction array dimension +!> @param[in] NK k-direction array dimension +!> @param[in] A_name array name (ascii) +!> @param[in] f_name file name +!> @param[out] A array with all data + SUBROUTINE read_open_txt_int(ni,nj,nk,a,a_name,f_name) + IMPLICIT NONE + character (len=*) :: a_name, f_name + character (len=80) :: line + INTEGER ni, nj, nk, i, j, k + INTEGER a(ni,nj,nk) + LOGICAL found + EXTERNAL found + + WRITE(*,*) ' open TXT file: ', f_name + OPEN(89,file=f_name,status='old',err=99) + IF (found(89,a_name,line,.TRUE.)) THEN + READ(89,*) (((a(i,j,k),i=1,ni),j=1,nj),k=1,nk) + END IF + CLOSE(89) + RETURN +! +99 WRITE(*,*) 'error: can not open file "', f_name, '" !' + STOP + END diff --git a/forward/old_restore.f90 b/forward/old_restore.f90 new file mode 100644 index 0000000..bb53d4d --- /dev/null +++ b/forward/old_restore.f90 @@ -0,0 +1,73 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief parallelisation wrapper for "omp_old_restore" +!> @param[in] level level number +!> @param[in] ismpl local sample index + SUBROUTINE old_restore(level,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + + INCLUDE 'OMP_TOOLS.inc' + INTEGER level + INTRINSIC abs + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(abs(ismpl)) +#endif + CALL omp_old_restore(level,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif +! + RETURN + END + +!> @brief restores an old state/version +!> @param[in] level level number (which old version) +!> @param[in] ismpl local sample index + SUBROUTINE omp_old_restore(level,ismpl) + use arrays + use mod_genrl + use mod_conc + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + INTEGER level, tpos, tanz + INTRINSIC abs, max + + CALL omp_part(i0*j0*k0,tpos,tanz) + CALL ijk_m(tpos,i,j,k) +! save state (before) + CALL dcopy(tanz,headold(tpos,level,abs(ismpl)),1, head(i,j,k,max(1,ismpl)), 1) + CALL dcopy(tanz,tempold(tpos,level,abs(ismpl)),1, temp(i,j,k,max(1,ismpl)), 1) + CALL dcopy(tanz,presold(tpos,level,abs(ismpl)),1, pres(i,j,k,max(1,ismpl)), 1) + DO l = 1, ntrans + CALL dcopy(tanz,concold(tpos,l,level,abs(ismpl)),1, conc(i,j,k,l,max(1,ismpl)),1) + END DO +! + RETURN + END diff --git a/forward/old_save.f90 b/forward/old_save.f90 new file mode 100644 index 0000000..282305c --- /dev/null +++ b/forward/old_save.f90 @@ -0,0 +1,99 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief parallelisation wrapper for "omp_old_save" +!> @param[in] level level number +!> @param[in] ismpl local sample index + subroutine old_save(level,ismpl) + + use mod_OMP_TOOLS, only: Tlevel_1 + + implicit none + + integer :: ismpl + + include 'OMP_TOOLS.inc' + + integer, intent (in) :: level + + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(abs(ismpl)) +#endif + + call omp_old_save(level,ismpl) + +#ifdef fOMP +!$OMP end parallel +#endif +! + return + + end subroutine old_save + +!> @brief save current state as an old version +!> @param[in] level level number (which old version) +!> @param[in] ismpl local sample index + subroutine omp_old_save(level,ismpl) + + use arrays + use mod_genrl + use mod_conc + + implicit none + + ! local sample index + integer :: ismpl + + ! cgen level index + integer, intent (in) :: level + + ! directional cell-indices + integer :: i, j, k + + ! counter for concentration + integer :: l + + ! Start position in array for process + integer :: tpos + + ! Number of array elements for process + integer :: tanz + + ! OpenMP partition, get tpos, tanz + call omp_part(i0*j0*k0,tpos,tanz) + + ! Get i, j, k indices for tpos + call ijk_m(tpos,i,j,k) + + ! Copy all variable arrays to old: var -> varold + call dcopy(tanz,head(i,j,k,abs(ismpl)),1, headold(tpos,level,max(1,ismpl)), 1) + call dcopy(tanz,temp(i,j,k,abs(ismpl)),1, tempold(tpos,level,max(1,ismpl)), 1) + call dcopy(tanz,pres(i,j,k,abs(ismpl)),1, presold(tpos,level,max(1,ismpl)), 1) + do l = 1, ntrans + call dcopy(tanz,conc(i,j,k,l,abs(ismpl)),1, concold(tpos,l,level,max(1,ismpl)),1) + end do + + return + + end subroutine omp_old_save diff --git a/forward/omp_bindtools.f90 b/forward/omp_bindtools.f90 new file mode 100644 index 0000000..eb6daa3 --- /dev/null +++ b/forward/omp_bindtools.f90 @@ -0,0 +1,262 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief init thread binding table for ScaleMP systems + SUBROUTINE init_scalemp_binding() + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! node-size: core number to use per node, offset for the next node + INTEGER node_size, node_offs + INTEGER o, i, bs, k, ni + ! INTEGER g_o, g_i +! binding table + INTEGER po, pi, mo, mi + PARAMETER (po=128) + PARAMETER (pi=128) + INTEGER (kind=4) btable(pi,po) + COMMON /binding_tab/mo, mi, btable +! node list + INTEGER inode_list(po+1), nnode + character (len=256) :: cnode_list +! error handler + INTEGER error +! + INTRINSIC trim, mod +#ifdef libnuma + INTEGER (kind=4) f_numa_num_configured_nodes + INTEGER (kind=4) f_numa_num_configured_cpus + INTEGER (kind=4) f_numa_available + EXTERNAL f_numa_num_configured_nodes + EXTERNAL f_numa_num_configured_cpus + EXTERNAL f_numa_available +#endif + +! default for old ScaleMP system (on RWTH Aachen university) + node_size = 8 + node_offs = node_size +#ifdef libnuma +! overwrite for modern systems using libnuma + IF (f_numa_available()==-1) THEN + WRITE(*,'(1A)') & + 'error: "libnuma" not working, see "omp_bindtools.f90"!' + STOP + END IF + node_size = f_numa_num_configured_cpus() / & + f_numa_num_configured_nodes() + node_offs = node_size + WRITE(*,'(1A,1I4)') ' [I] : ccNUMA nodes = ', & + f_numa_num_configured_nodes() + WRITE(*,'(1A,1I4)') & + ' [I] : cores per ccNUMA node = ', node_size +#endif +! + CALL get_environment_variable(name='JOB_NODE_LIST', & + value=cnode_list,status=error) + IF (error==0) THEN +! default value to overwrite + DO i = 1, po + 1 + inode_list(i) = -1 + END DO + WRITE(*,*) ' [I] : JOB_NODE_LIST = "', trim(cnode_list), & + '"' +! read node list + READ(cnode_list,*,err=101,end=101) (inode_list(i),i=1,po) +101 nnode = 0 +! count node number + DO i = 1, po + IF (inode_list(i)>=0) nnode = nnode + 1 + END DO + ELSE +! default setup, assume all nodes + WRITE(*,'(2A)') ' <D> : JOB_NODE_LIST not defined,', & + ' using all ccNUMA nodes' + nnode = 1 +#ifdef libnuma + nnode = f_numa_num_configured_nodes() +#endif + DO i = 1, nnode + inode_list(i) = i-1 + END DO + inode_list(nnode+1) = -1 + END IF + WRITE(*,'(1A,999I6)') ' nodes = ', & + (inode_list(i),i=1,nnode) +! + mi = tlevel_1 + mo = tlevel_0 +! threading block size [bs] for inner parallel region + bs = (node_size*nnode) / tlevel_0 +! + IF (bs>=tlevel_1) THEN + WRITE(*,'(1A,3I6)') ' [I] : binding mode = memory distance' +! compute binding list + DO o = 1, mo + DO i = 1, mi + k = (o-1)*bs +(i-1)*bs/tlevel_1 + ni = k / node_size + 1 + btable(i,o) = inode_list(ni)*node_offs +k-(ni-1)*node_size + END DO + END DO + ELSE + WRITE(*,*) ' [E] : not enough cores for all threads' + STOP + END IF +! show table + WRITE(*,*) ' [I] : binding table' + WRITE(*,'(1A,2I6)') ' ', mo, mi + DO o = 1, mo + WRITE(*,'(1A,128I6)') ' ', (btable(i,o),i=1,mi) + END DO +! + RETURN + END + +!> @brief load thread binding table +!> @param[in] fname file name of the table + SUBROUTINE load_binding(fname) + IMPLICIT NONE + character (len=*) :: fname + INTEGER po, pi, mo, mi +#ifdef TBIND + INTEGER o, i +#endif + PARAMETER (po=128) + PARAMETER (pi=128) + INTEGER (kind=4) :: btable(pi,po) + COMMON /binding_tab/mo, mi, btable + INTRINSIC trim + +#ifdef TBIND + IF (fname=='default') THEN + WRITE(*,*) ' <D> : no thread binding' + mo = 0 + mi = 0 + ELSE + WRITE(*,*) ' [R] : thread binding table from "', & + trim(fname), '"' + OPEN(81,file=fname,status='OLD',err=100) + READ(81,*) mo, mi + IF (mo>po .OR. mi>pi .OR. mo<=0 .OR. mi<=0) THEN + WRITE(*,'(2(1A,1I4),1A)') & + 'error: processor binding table exceed limits (', po, & + 'x', pi, ') in "load_binding" !' + STOP + END IF + DO o = 1, mo + READ(81,*) (btable(i,o),i=1,mi) + END DO + CLOSE(81) + END IF +! show table + WRITE(*,*) ' [I] : binding table' + WRITE(*,'(1A,2I6)') ' ', mo, mi + DO o = 1, mo + WRITE(*,'(1A,128I6)') ' ', (btable(i,o),i=1,mi) + END DO +#endif + RETURN +#ifdef TBIND +100 WRITE(*,'(3A)') 'error: can not open map file "', & + trim(fname), '" !' +#endif + STOP + END + +!> @brief try thread binding +!> @param[in] o outer thread index + SUBROUTINE omp_binding(o) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + INTEGER o +#ifdef TBIND + INTEGER lo +#endif + INCLUDE 'OMP_TOOLS.inc' + INTEGER p_o, p_i, mo, mi + PARAMETER (p_o=128) + PARAMETER (p_i=128) + INTEGER (kind=4) :: btable(p_i,p_o) + COMMON /binding_tab/mo, mi, btable +! master binding staff +#ifdef TBIND + INTEGER (kind=4) :: p_is +#endif +#ifdef libnuma + INTEGER (kind=4) :: f_numa_run_on_node + INTEGER (kind=4 :: f_numa_node_of_cpu + INTEGER (kind=4) :: f_numa_available + EXTERNAL f_numa_run_on_node + EXTERNAL f_numa_node_of_cpu + EXTERNAL f_numa_available +#endif + INTRINSIC mod + +#ifdef libnuma + IF (f_numa_available()==-1) THEN + WRITE(*,'(1A)') & + 'error: "libnuma" not working, see "omp_bindtools.f90"!' + STOP + END IF +#endif +#ifdef TBIND +! binding enabled? + IF (mo==0 .OR. mi==0) RETURN +! + i = omp_get_his_thread_num() + 1 + lo = o +! special handling for ENKF/SIMUL, when fewer threads than realisations + IF (lo>Tlevel_0 .AND. lo<=nsmpl) lo = mod(lo-1,Tlevel_0) +1 +! + IF (lo>mo .OR. i>mi .OR. lo<1 .OR. i<1) THEN + WRITE(*,'(2(1A,1I4),1A)') & + 'error: processor binding table exceed limits (', mo, 'x', & + mi, ') in "omp_binding" !' + WRITE(*,'(2(1A,1I4),1A)') & + ' for processor binding on (', lo, 'x', i, ')' + STOP + END IF +#ifdef libnuma + IF (f_numa_run_on_node(f_numa_node_of_cpu(btable(i,lo)))<0) THEN + WRITE(*,'(1A)') & + 'error: "libnuma" not working, see "omp_bindtools.f90"!' + STOP + END IF +#else +#ifndef G95 +! Intel, PGI, SUN + CALL r_processorbind(btable(i,lo)) +#else +! GNU 4.xx, to avoid THREAD-spinning on the master affinity + IF (i>1) THEN + CALL r_processorbind(btable(i,lo)) + ELSE +! (GNU compiler workaround) bind the master thread on all team cores (group binding) + p_is = mi + CALL r_groupbind(p_is,btable(1,lo)) + END IF +#endif +#endif +#endif + RETURN + END diff --git a/forward/omp_file_handler.f90 b/forward/omp_file_handler.f90 new file mode 100644 index 0000000..372094a --- /dev/null +++ b/forward/omp_file_handler.f90 @@ -0,0 +1,94 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief create a new file handler (number) +!> @param[out] fh file handler (number) +!> @param[in] i 0: reset file handler table, >0 : handler index, specific for each thread + SUBROUTINE omp_new_file_handler(fh,i) + use arrays + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + INTEGER fh, i, o, l2 + +! reset the file-handler table + IF (i==0) THEN + l2 = tlevel_0 + DO fh = 1, c_fhandler + DO o = 1, l2 + fh_table(fh,o) = 0 + END DO + END DO + fh = -1 + RETURN + END IF +! + o = omp_get_his_thread_num() +! looking for an already used file-handler (for this thread) + DO l2 = 1, c_fhandler + IF (fh_table(l2,o+1)==i) THEN + fh = l2 + o*c_fhandler + c_foffset + RETURN + END IF + END DO +! looking for a free file-handler (not used from any thread) + DO l2 = 1, c_fhandler + IF (fh_table(l2,o+1)==0) THEN + fh_table(l2,o+1) = i + fh = l2 + o*c_fhandler + c_foffset + RETURN + END IF + END DO +! error handler + WRITE(*,'(1A,1I4,1A)') 'error: max number (', c_fhandler, & + ') of open files per thread, in "omp_file_handler.f" !' + STOP + END + +!> @brief remove used file handler (number) +!> @param[in,out] fh file handler (number), gets 0 when successful + SUBROUTINE omp_del_file_handler(fh) + use arrays + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + INTEGER fh, o, l2 + + o = omp_get_his_thread_num() + l2 = fh - o*c_fhandler - c_foffset +! sanity check + IF (l2<=0 .OR. l2>c_fhandler) THEN + WRITE(*,'(1A)') & + 'error: wrong file-handler, in "omp_file_handler.f" !' + STOP + END IF +! free the already used file-handler + IF (fh_table(l2,o+1)/=0) THEN + fh_table(l2,o+1) = 0 + fh = 0 + RETURN + END IF +! error handler + WRITE(*,'(1A,1I4,1A)') 'error: file-handler ', fh, & + ' already closed, in "omp_file_handler.f" !' + STOP + END diff --git a/forward/omp_libnuma.c b/forward/omp_libnuma.c new file mode 100644 index 0000000..7951aa3 --- /dev/null +++ b/forward/omp_libnuma.c @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +#ifdef libnuma +#include <numa.h> + +int f_numa_node_of_cpu_(int *id) +{ + return(numa_node_of_cpu(*id)); +} + +int f_numa_run_on_node_(int *id) +{ + return(numa_run_on_node(*id)); +} + +int f_numa_num_configured_nodes_() +{ + return(numa_num_configured_nodes()); +} + +int f_numa_num_configured_cpus_() +{ + return(numa_num_configured_cpus()); +} + +int f_numa_available_() +{ + return(numa_available()); +} +#endif diff --git a/forward/omp_summe.f90 b/forward/omp_summe.f90 new file mode 100644 index 0000000..87df45d --- /dev/null +++ b/forward/omp_summe.f90 @@ -0,0 +1,139 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP "reduction" collection used in Courant/Peclet/Neumann computations +!> @param[in,out] dval_maxx max X value +!> @param[in,out] dval_minx min X value +!> @param[in,out] dval_avgx sum, X value +!> @param[in,out] dval_maxy max Y value +!> @param[in,out] dval_miny min Y value +!> @param[in,out] dval_avgy sum, Y value +!> @param[in,out] dval_maxz max Z value +!> @param[in,out] dval_minz min Z value +!> @param[in,out] dval_avgz sum, Z value +!> @param[in,out] c1 number in X +!> @param[in,out] c2 number in Y +!> @param[in,out] c3 number in Z +!> @param[in] ismpl local sample index +!> @details +!> computes global (inter) thread maximum, minimum and sum (float and integer)\n + SUBROUTINE omp_summe(dval_maxx,dval_minx,dval_avgx,dval_maxy, & + dval_miny,dval_avgy,dval_maxz,dval_minz,dval_avgz,c1,c2,c3, & + ismpl) + use arrays + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION dval_maxx, dval_minx, dval_avgx, dval_maxy, & + dval_miny, dval_avgy, dval_maxz, dval_minz, dval_avgz + INTEGER c1, c2, c3, myid + +! each thread needs to set its private values in the global arrays + myid = omp_get_his_thread_num() + 1 +! + omp_dglobal(myid,1,ismpl) = dval_maxx + omp_dglobal(myid,2,ismpl) = dval_minx + omp_dglobal(myid,3,ismpl) = dval_avgx +! + omp_dglobal(myid,4,ismpl) = dval_maxy + omp_dglobal(myid,5,ismpl) = dval_miny + omp_dglobal(myid,6,ismpl) = dval_avgy +! + omp_dglobal(myid,7,ismpl) = dval_maxz + omp_dglobal(myid,8,ismpl) = dval_minz + omp_dglobal(myid,9,ismpl) = dval_avgz +! + omp_iglobal(myid,1,ismpl) = c1 + omp_iglobal(myid,2,ismpl) = c2 + omp_iglobal(myid,3,ismpl) = c3 +! +! global OpenMP reduction +!$OMP barrier +!$OMP master +! fast OpenMP reduction MAX + DO i = 2, tlevel_1 + omp_dglobal(1,1,ismpl) = max(omp_dglobal(1,1,ismpl), & + omp_dglobal(i,1,ismpl)) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,4,ismpl) = max(omp_dglobal(1,4,ismpl), & + omp_dglobal(i,4,ismpl)) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,7,ismpl) = max(omp_dglobal(1,7,ismpl), & + omp_dglobal(i,7,ismpl)) + END DO +! fast OpenMP reduction MIN + DO i = 2, tlevel_1 + omp_dglobal(1,2,ismpl) = min(omp_dglobal(1,2,ismpl), & + omp_dglobal(i,2,ismpl)) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,5,ismpl) = min(omp_dglobal(1,5,ismpl), & + omp_dglobal(i,5,ismpl)) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,8,ismpl) = min(omp_dglobal(1,8,ismpl), & + omp_dglobal(i,8,ismpl)) + END DO +! fast OpenMP reduction SUM + DO i = 2, tlevel_1 + omp_dglobal(1,3,ismpl) = omp_dglobal(1,3,ismpl) + & + omp_dglobal(i,3,ismpl) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,6,ismpl) = omp_dglobal(1,6,ismpl) + & + omp_dglobal(i,6,ismpl) + END DO + DO i = 2, tlevel_1 + omp_dglobal(1,9,ismpl) = omp_dglobal(1,9,ismpl) + & + omp_dglobal(i,9,ismpl) + END DO +! fast OpenMP reduction SUM (integer) + DO j = 1, 3 + DO i = 2, tlevel_1 + omp_iglobal(1,j,ismpl) = omp_iglobal(1,j,ismpl) + & + omp_iglobal(i,j,ismpl) + END DO + END DO +!$OMP end master +!$OMP barrier +! +! each thread gets its own copy of the global reduction + dval_maxx = omp_dglobal(1,1,ismpl) + dval_minx = omp_dglobal(1,2,ismpl) + dval_avgx = omp_dglobal(1,3,ismpl) + dval_maxy = omp_dglobal(1,4,ismpl) + dval_miny = omp_dglobal(1,5,ismpl) + dval_avgy = omp_dglobal(1,6,ismpl) + dval_maxz = omp_dglobal(1,7,ismpl) + dval_minz = omp_dglobal(1,8,ismpl) + dval_avgz = omp_dglobal(1,9,ismpl) + c1 = omp_iglobal(1,1,ismpl) + c2 = omp_iglobal(1,2,ismpl) + c3 = omp_iglobal(1,3,ismpl) +! + RETURN + END diff --git a/forward/output/write_data.f90 b/forward/output/write_data.f90 new file mode 100644 index 0000000..4009a44 --- /dev/null +++ b/forward/output/write_data.f90 @@ -0,0 +1,113 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief shows observation data differences +!> @param[in] ident index number for file name +!> @param[in] ismpl local sample index + SUBROUTINE write_data(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_data + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + INCLUDE 'version.inc' +! + DOUBLE PRECISION res, val, resn + INTEGER i1s, i2s, i1, i2, i3, i4, ui, i_type, ozone, ident, & + lblank, i_si, lout + EXTERNAL lblank + character (len=80) :: filename + character (len=20) :: snumber + + + IF (write_disable) RETURN +#ifdef NOOUT + RETURN +#endif + IF (ndata<=0) RETURN + + CALL omp_new_file_handler(lout,16) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '.dat' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.dat' + END IF + + OPEN(lout,file=filename,status='unknown',blank='null') + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Data to "', & + filename(1:lblank(filename)), '"' + END IF + + WRITE(lout,'(2A)') '% Shemat-Suite version: ', version + WRITE(lout,'(2A)') '% data fit at iteration ', snumber + WRITE(lout,'(3A)') '% i j k unit type ', & + ' calc obs err', & + ' diff res time ozone' + + DO l = 1, ndata + i = idata(l,cid_i) + j = idata(l,cid_j) + k = idata(l,cid_k) + ui = uindex(i,j,k) + i_type = idata(l,cid_pv) + i_si = idata(l,cid_si) + ozone = idata(l,cid_obs) + val = sdata(l,ismpl) + + res = val - ddata(l,cdd_pv) + resn = res/ddata(l,cdd_w) + WRITE(lout,'(3i6,3x,i6,3x,i6,3x,6e16.8,i6)') i, j, k, ui, & + i_type, val, ddata(l,cdd_pv), ddata(l,cdd_w), res, resn, & + ddata(l,cdd_time), ozone + END DO + + CLOSE(lout) + CALL omp_del_file_handler(lout) + + RETURN + END diff --git a/forward/output/write_dense3d.f90 b/forward/output/write_dense3d.f90 new file mode 100644 index 0000000..6f032b5 --- /dev/null +++ b/forward/output/write_dense3d.f90 @@ -0,0 +1,90 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief write values in fortran77 compressed text form +!> @param[in] A value array to write +!> @param[in] I0 i-dimension +!> @param[in] J0 j-dimension +!> @param[in] K0 k-dimension +!> @param[in] CHAN file handler +!> @param[in] ismpl local sample index + SUBROUTINE write_dense3d(a,i0,j0,k0,chan,ismpl) + IMPLICIT NONE + INTEGER i0, j0, k0, i, chan, g, nijk, ismpl + DOUBLE PRECISION a(i0*j0*k0), va, vn +! Intel compiler buffer workaround + INTEGER maxb, l10, lenb + PARAMETER (lenb=65536) +! character (len=lenB) :: rowbuffer + character (len=65536) :: rowbuffer +! format buffer + character (len=25) :: element + INTRINSIC dabs, int, log, dble + +! init + nijk = i0*j0*k0 + IF (nijk<=0) RETURN + + g = 1 + maxb = 1 + va = a(1) + IF (dabs(va)<1.0D-99) va = 0.0D0 + rowbuffer = ' ' + +! compute minimal place holder for the counter + l10 = int(log(dble(nijk+1))/log(10.0D0)) + 1 + element = '(I' // achar(l10+48) // ',A1,SP,1e24.17,A1)' + + DO i = 2, nijk + vn = a(i) + IF (dabs(vn)<1.0D-99) vn = 0.0D0 + IF (vn/=va) THEN + IF (g==1) THEN + WRITE(rowbuffer(maxb:maxb+25),'(A1,SP,e24.17,A1)') ' ', & + va, ',' + maxb = maxb + 26 + g = 0 + ELSE + WRITE(rowbuffer(maxb:maxb+25+l10),element) g, '*', va, & + ',' + maxb = maxb + 26 + l10 + g = 0 + END IF + IF (maxb>=(lenb-26-l10)) THEN + WRITE(chan,'(A)') rowbuffer(1:maxb-1) + maxb = 1 + END IF + va = vn + END IF + g = g + 1 + END DO + IF (g==1) THEN + WRITE(rowbuffer(maxb:maxb+24),'(A1,SP,1e24.17)') ' ', va + maxb = maxb + 25 + ELSE + WRITE(rowbuffer(maxb:maxb+25+l10),element) g, '*', va, ' ' + maxb = maxb + 26 + l10 + END IF + WRITE(chan,'(A)') rowbuffer(1:maxb-1) + + RETURN + END diff --git a/forward/output/write_logs.f90 b/forward/output/write_logs.f90 new file mode 100644 index 0000000..9f7b748 --- /dev/null +++ b/forward/output/write_logs.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief write borehole logs to different files +!> @param[in] ident index number for file name +!> @param[in] ismpl local sample index + SUBROUTINE write_logs(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_data + use mod_linfos + IMPLICIT NONE + integer :: i, j, k + integer :: ismpl + INCLUDE 'version.inc' +! + INTEGER i1s, i2s, i1, i2, i3, i4, ui, ident, lblank, lout + EXTERNAL lblank + character (len=256) :: filename + character (len=20) :: snumber + INTRINSIC trim + + IF (write_disable) RETURN +#ifdef NOOUT + RETURN +#endif + IF (nbh_logs<=0) RETURN +! + CALL omp_new_file_handler(lout,16) +! + DO ui = 1, nbh_logs + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) +! + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '_'//trim(cbh_name(ui))//'.dat' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '_'//trim(cbh_name(ui))//'.dat' + END IF +! + OPEN(lout,file=filename,status='unknown',blank='null') +! + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Borehole logs to "', & + filename(1:lblank(filename)), '"' + END IF +! +! writing logs at BHT locations + i = ibh_pos(1,ui) + j = ibh_pos(2,ui) + DO k=1,k0 + WRITE(lout,FMT='(20G23.15)') temp(i,j,k,ismpl),head(i,j,k,ismpl),pres(i,j,k,ismpl),delz(k),uindex(i,j,k) + END DO +! + CLOSE(lout) + END DO +! + CALL omp_del_file_handler(lout) +! + RETURN + END diff --git a/forward/output/write_monitor.f90 b/forward/output/write_monitor.f90 new file mode 100644 index 0000000..d0384d9 --- /dev/null +++ b/forward/output/write_monitor.f90 @@ -0,0 +1,303 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes data in tecplot-format +!> @param[in] otype 1: new file, 2 append +!> @param[in] ismpl local sample index + SUBROUTINE write_monitor(otype,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, m + integer :: ib + DOUBLE PRECISION dx, dy, dz, val +! otype: +! 1 new file +! 2 append + INTEGER otype +! mm_*: outer iteration loop (file for each monitor point) +! mt_*: inner iteration loop (file for each time step) + INTEGER mm_b, mm_e, mt_b, mt_e + INTEGER i1, i2, i3, m2, lblank, lout, in1, in2 + EXTERNAL lblank +! external functions + DOUBLE PRECISION vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, & + rhof, visf + EXTERNAL vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, rhof, & + visf + DOUBLE PRECISION qxc, qyc, qzc, bhpr + EXTERNAL qxc, qyc, qzc, bhpr +! normal or transposed, monitor point files, time step files + LOGICAL ltransposed, lmonip, ltimes + + character (len=256) :: filename + character (len=65536) :: line + character (len=8) :: snumber + INTRINSIC trim + + + IF ( .NOT. (transient .AND. tr_switch(ismpl))) RETURN + IF ( .NOT. monitor) RETURN + IF ( .NOT. write_smonitor) THEN + IF (write_disable) RETURN + END IF +#ifdef NOMON + RETURN +#endif + + snumber = '0' + IF (write_smonitor) THEN + WRITE(snumber,'(1I7)') smon_idx(ismpl) + IF (smon_idx(ismpl)>=0) THEN + WRITE(snumber,'(1I7)') smon_idx(ismpl) + ELSE IF (smon_idx(ismpl)==-1) THEN + WRITE(snumber,'(A8)') 'final' + ELSE IF (smon_idx(ismpl)==-2) THEN + WRITE(snumber,'(A8)') 'debug' + ELSE IF (smon_idx(ismpl)==-3) THEN + WRITE(snumber,'(A8)') 'ens_mean' + ELSE IF (smon_idx(ismpl)==-4) THEN + WRITE(snumber,'(A8)') 'mean' + ELSE IF (smon_idx(ismpl)==-5) THEN + WRITE(snumber,'(A8)') 'ens_mean' + END IF + END IF + CALL chln(snumber,in1,in2) + + CALL omp_new_file_handler(lout,16) + +! out_orientation: +! 0 normal (pv column wise), each time step has its own block (mp row wise) +! 1 transposed (pv row wise), each time step has its own block (mp column wise) +! 2 normal (pv column wise), new file for each time step (mp row wise) +! 3 transposed (pv row wise), new file for each time step (mp column wise) +! 4 normal (pv column wise), new file for each monitor point (time row wise) + IF (out_orientation==1 .OR. out_orientation==3) THEN + ltransposed = .TRUE. + ELSE + ltransposed = .FALSE. + END IF + IF (out_orientation==4) THEN +! setup outer iteration + mm_b = 1 + mm_e = nmon +! inner loop makes only one step, computed later + mt_b = 0 + mt_e = 0 + lmonip = .TRUE. + ELSE +! outer loop makes only one dummy step + mm_b = 1 + mm_e = 1 +! setup inner iteration + mt_b = 1 + mt_e = nmon + lmonip = .FALSE. + END IF + IF (out_orientation==2 .OR. out_orientation==3) THEN + ltimes = .TRUE. + ELSE + ltimes = .FALSE. + END IF + + IF (nmon>9999 .AND. ltransposed) THEN + WRITE(*,'(1A)') & + 'error: number of monitor points limited to 9999!' + STOP + END IF + + CALL chln(project,i1,i2) +! steady state - file name + WRITE(filename,'(3A)') project(i1:i2),trim(project_sfx(ismpl)), '_monitor.dat' + IF (write_smonitor) WRITE(filename,'(5A)') project(i1:i2),trim(project_sfx(ismpl)), & + '_monitor_', snumber(in1:in2), '.dat' +! transient - file name + IF (ltimes) THEN + WRITE(filename,'(3A,1e15.9,1A)') project(i1:i2),trim(project_sfx(ismpl)), '_', & + (simtime(ismpl))/tunit, '_monitor.dat' + IF (write_smonitor) WRITE(filename,'(3A,1e15.9,3A)') & + project(i1:i2),trim(project_sfx(ismpl)), '_', (simtime(ismpl))/tunit, & + '_monitor_', snumber(in1:in2), '.dat' + END IF + + IF (linfos(3)>=2 .AND. .NOT. lmonip) THEN + WRITE(*,'(3A)') ' [W] : Monitor points to "', & + filename(1:lblank(filename)), '"' + END IF + +! ---------------------------------------------- + DO m = mm_b, mm_e + IF (lmonip) THEN +! compute inner loop, one step with the right index + mt_b = m + mt_e = m +! monitor point - file name + CALL chln(project,i1,i2) + WRITE(filename,'(3A,1I6.6,1A)') project(i1:i2),trim(project_sfx(ismpl)), '_', m, & + '_monitor.dat' + IF (write_smonitor) WRITE(filename,'(3A,1I6.6,3A)') & + project(i1:i2),trim(project_sfx(ismpl)), '_', m, '_monitor_', snumber(in1:in2), & + '.dat' + IF (linfos(3)>=2) THEN + WRITE(*,'(3A)') ' [W] : Monitor points to "', & + filename(1:lblank(filename)), '"' + END IF + END IF + +! Header + IF ((otype==1 .OR. ltimes) .AND. .NOT. ltransposed) THEN + WRITE(line,'(9999(1A11,1I4.4,1A2))') & + (' "conc', i, '",',i=1,ntrans) + OPEN(lout,file=filename,status='replace') + WRITE(lout,'(12A)') '% "time" "x" ', & + ' "y" "z" "uindex" ', & + ' "i" "j" "k"', ' "head" ', & + ' "temp" ', ' "pres" ', & + line(1:ntrans*17), & + ' "vx" ', ' "vy" ', & + ' "vz" ', ' "bhpr"', & + ' "kz" ' + CLOSE(lout) + END IF + IF ((otype==1 .OR. ltimes) .AND. ltransposed) THEN + OPEN(lout,file=filename,status='replace') + WRITE(lout,'(1A)') '% "x"' + WRITE(lout,'(1A)') '% "y"' + WRITE(lout,'(1A)') '% "z"' + WRITE(lout,'(1A)') '% "uindex"' + WRITE(lout,'(1A)') '% "i"' + WRITE(lout,'(1A)') '% "j"' + WRITE(lout,'(1A)') '% "k"' + DO m2 = mt_b, mt_e + i1 = imon(m2,1) + dx = 0.5D0*delx(1) + DO i = 2, i1 + dx = dx + 0.5D0*(delx(i-1)+delx(i)) + END DO + WRITE(lout,'(1e14.6,1X)',advance='NO') dx + END DO + WRITE(lout,*) ' ' + DO m2 = mt_b, mt_e + i2 = imon(m2,2) + dy = 0.5D0*dely(1) + DO j = 2, i2 + dy = dy + 0.5D0*(dely(j-1)+dely(j)) + END DO + WRITE(lout,'(1e14.6,1X)',advance='NO') dy + END DO + WRITE(lout,*) ' ' + DO m2 = mt_b, mt_e + i3 = imon(m2,3) + dz = 0.5D0*delz(1) + DO k = 2, i3 + dz = dz + 0.5D0*(delz(k-1)+delz(k)) + END DO + WRITE(lout,'(1e14.6,1X)',advance='NO') dz + END DO + WRITE(lout,*) ' ' + WRITE(lout,'(9999(I14,1X))') (uindex(imon(m2,1),imon(m2,2),imon(m2,3)),m2=mt_b,mt_e) + WRITE(lout,'(9999(I14,1X))') (imon(m2,1),m2=mt_b,mt_e) + WRITE(lout,'(9999(I14,1X))') (imon(m2,2),m2=mt_b,mt_e) + WRITE(lout,'(9999(I14,1X))') (imon(m2,3),m2=mt_b,mt_e) + WRITE(lout,'(1A)') '% "head"' + WRITE(lout,'(1A)') '% "temp"' + WRITE(lout,'(1A)') '% "pres"' + DO i = 1, ntrans + WRITE(lout,'(1A7,1I4.4,1A1)') '% "conc', i, '"' + END DO + WRITE(lout,'(1A)') '% "vx"' + WRITE(lout,'(1A)') '% "vy"' + WRITE(lout,'(1A)') '% "vz"' + CLOSE(lout) + END IF + +! append data block + OPEN(lout,file=filename,status='unknown',position='append') + +! Body + IF ( .NOT. ltransposed) THEN +! - normal orientation - +! separate each time steps + IF ( .NOT. ltimes .AND. .NOT. lmonip) WRITE(lout,'(A)') '%' +! - inner loop - + DO m2 = mt_b, mt_e + i3 = imon(m2,3) + i2 = imon(m2,2) + i1 = imon(m2,1) + dz = 0.5D0*delz(1) +! + val = 0.0d0 + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) +! "neumann"?, skip otherwise + IF (ibc_data(ib,cbc_bt)==bt_neuw.AND.i==i1.AND.j==i2.AND.k==i3) THEN + IF (ibc_data(ib,cbc_bcu)>0) THEN + WRITE(*,*) 'error: well function can not be defined in a BC-unit!' + STOP + END IF +!better-recompute-all-times instead of: val = dbc_data(ib,3,ismpl) + val = bhpr(i,j,k,ismpl) + END IF + END DO +! + WRITE(lout, & + '(1e17.9,3(e14.6,1X),1I9,3I6,9999(e16.8,1X))') & + (simtime(ismpl))/tunit, delxa(i1), delya(i2), delza(i3), & + uindex(i1,i2,i3), i1, i2, i3, head(i1,i2,i3,ismpl), & + temp(i1,i2,i3,ismpl), pres(i1,i2,i3,ismpl)*pa_conv1, & + (conc(i1,i2,i3,i,ismpl),i=1, & + ntrans), vxc(i1,i2,i3,ismpl), & + vyc(i1,i2,i3,ismpl), vzc(i1,i2,i3,ismpl),val*pa_conv1, & + kz(i1,i2,i3,ismpl) + END DO + ELSE +! - transposed orientation - +! time comment + WRITE(lout,'(1A,1e17.9)') '% "time: "', (simtime(ismpl))/tunit + WRITE(lout,'(9999(e14.6,1X))') (head(imon(m2,1),imon(m2,2),imon(m2,3),ismpl),m2=mt_b,mt_e) + WRITE(lout,'(9999(e14.6,1X))') (temp(imon(m2,1),imon(m2,2),imon(m2,3),ismpl),m2=mt_b,mt_e) + WRITE(lout,'(9999(e14.6,1X))') (pres(imon(m2,1),imon(m2,2),imon(m2,3),ismpl)*pa_conv1,m2=mt_b,mt_e) + DO i = 1, ntrans + WRITE(lout,'(9999(e14.6,1X))') (conc(imon(m2,1),imon(m2,2),imon(m2,3),i,ismpl),m2=mt_b,mt_e) + END DO + WRITE(lout,'(9999(e14.6,1X))') (vxc(imon(m2,1),imon(m2,2),imon(m2,3),ismpl),m2=mt_b,mt_e) + WRITE(lout,'(9999(e14.6,1X))') (vyc(imon(m2,1),imon(m2,2),imon(m2,3),ismpl),m2=mt_b,mt_e) + WRITE(lout,'(9999(e14.6,1X))') (vzc(imon(m2,1),imon(m2,2),imon(m2,3),ismpl),m2=mt_b,mt_e) + END IF + + CLOSE(lout) + END DO +! ---------------------------------------------- + CALL omp_del_file_handler(lout) + + RETURN + END diff --git a/forward/output/write_outt.f90 b/forward/output/write_outt.f90 new file mode 100644 index 0000000..41b9d54 --- /dev/null +++ b/forward/output/write_outt.f90 @@ -0,0 +1,102 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief determine output times, interpolate, and call the write routine +!> @param[in] deltt time step length +!> @param[in] ismpl local sample index + SUBROUTINE write_outt(deltt,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_time + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION deltt, talfa, malfa, numdiff + DOUBLE PRECISION, ALLOCATABLE :: tmp_new(:,:) + INTEGER ijk0, id, ii, i1, i2, i3, i4 + character (len=80) :: sfx_old + INTRINSIC trim + + + IF (write_disable) RETURN + +! allowed numerical difference + numdiff = 1.D-14*tunit + + id = 0 + DO i = 1, noutt + 1 + IF (outt(i)>simtime(ismpl)+numdiff) THEN + id = i - 1 + GO TO 100 + END IF + END DO + +100 IF (id==0) THEN +! no output + RETURN + ELSE IF (outt(id)>simtime(ismpl)-deltt+numdiff .AND. & + outt(id)<=simtime(ismpl)+numdiff) THEN +! time interval match + ijk0 = i0*j0*k0 +! save current main values + ALLOCATE(tmp_new(ijk0,5)) + CALL dcopy(ijk0,head(1,1,1,ismpl),1,tmp_new(1,1),1) + CALL dcopy(ijk0,temp(1,1,1,ismpl),1,tmp_new(1,2),1) + CALL dcopy(ijk0,pres(1,1,1,ismpl),1,tmp_new(1,3),1) + CALL dcopy(ijk0,conc(1,1,1,1,ismpl),1,tmp_new(1,5),1) + + CALL old_restore(cgen_time,ismpl) + ii = 0 +! interpolate + talfa = (simtime(ismpl)-outt(id))/deltt + malfa = 1.0D0 - talfa + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + ii = ii + 1 + head(i,j,k,ismpl) = talfa*head(i,j,k,ismpl) + malfa*tmp_new(ii,1) + temp(i,j,k,ismpl) = talfa*temp(i,j,k,ismpl) + malfa*tmp_new(ii,2) + pres(i,j,k,ismpl) = talfa*pres(i,j,k,ismpl) + malfa*tmp_new(ii,3) + conc(i,j,k,1,ismpl) = talfa*conc(i,j,k,1,ismpl) + malfa*tmp_new(ii,5) + END DO + END DO + END DO + + sfx_old = project_sfx(ismpl) + project_sfx(ismpl) = trim(sfx_old) // '_time' // & + '_out' + CALL forward_write(id,ismpl) + project_sfx(ismpl) = sfx_old + + +! restore current main values + CALL dcopy(ijk0,tmp_new(1,1),1,head(1,1,1,ismpl),1) + CALL dcopy(ijk0,tmp_new(1,2),1,temp(1,1,1,ismpl),1) + CALL dcopy(ijk0,tmp_new(1,3),1,pres(1,1,1,ismpl),1) + CALL dcopy(ijk0,tmp_new(1,5),1,conc(1,1,1,1,ismpl),1) + DEALLOCATE(tmp_new) + END IF + + RETURN + END diff --git a/forward/output/write_status_log.f90 b/forward/output/write_status_log.f90 new file mode 100644 index 0000000..6341538 --- /dev/null +++ b/forward/output/write_status_log.f90 @@ -0,0 +1,64 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief naming status.log file and writing header +!> @param[in] filename input filename as read from shemade.job +!> @param[inout] ismpl local sample index +!> @details +!> The status.log file is named and the header is written. +subroutine write_status_log(filename, ismpl) + + use mod_genrlc, only: status_log + use mod_time, only: transient + + implicit none + + integer :: ismpl + + character (len=80), intent (in) :: filename + + INCLUDE 'version.inc' + + integer, external :: lblank + logical, external :: test_option + + status_log = filename(1:lblank(filename)) // '_status.log' + + WRITE(*,'(3A)') ' [W] : "', status_log(1:lblank(status_log)), '"' + OPEN(76,file=status_log) + WRITE(76,'(2A)') '% Shemat-Suite version: ', version + WRITE(76,'(2A)') '% build: ', datum + WRITE(76,'(2A)') '% build command line: ', makecmd + WRITE(76,'(3A)') '% Project: "', filename(1:lblank(filename)), '"' + WRITE(76,'(1A)') '%' + IF (transient) THEN + WRITE(76,'(3A)') '% <time step>', ' <deltat>', ' <cum time>' + END IF +#ifdef head_base + WRITE(76,'(4A)') '% <iteration>',' <delta head>',' <delta temp>',' (<delta conc> ...)' +#endif +#ifdef pres_base + WRITE(76,'(4A)') '% <iteration>',' <delta pres>',' <delta temp>',' (<delta conc> ...)' +#endif + CLOSE(76) + +end subroutine write_status_log diff --git a/forward/output/write_tecdiff.f90 b/forward/output/write_tecdiff.f90 new file mode 100644 index 0000000..953caea --- /dev/null +++ b/forward/output/write_tecdiff.f90 @@ -0,0 +1,137 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes diff data in tecplot-format +!> @param[in] ident index number for output +!> @param[in] ismpl local sample index + SUBROUTINE write_tecdiff(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + + + + + + DOUBLE PRECISION dx, dy, dz + INTEGER i1, i2, i3, i4, i1s, i2s, ident, lblank, idx, lout, & + locstr, clast + EXTERNAL lblank, locstr, clast + character (len=256) :: filename + character (len=20) :: snumber + character (len=1024) :: sline + + + IF (write_disable) RETURN + + CALL omp_new_file_handler(lout,16) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '_diff.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // '_' // & + snumber(i3:i4), '"' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // & + project_sfx(ismpl) (i1s:i2s) // '_' // snumber(i3:i4), '"' + END IF + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Diffs in Tecplot to "', & + filename(1:lblank(filename)), '"' + END IF + + WRITE(lout,'(3A)') & + 'variables = "x", "y", "z","uindex","i","j","k",', & + ' "head", "temp",', & + ' "pres"' + +! use sline for ZONE string + i1 = locstr(project_sfx(ismpl),'_time_') + i2 = locstr(project_sfx(ismpl),'_out') + IF (i1>=1 .AND. i2>=1) THEN + WRITE(sline,'(1A,1I7,3A,1I7)') 'zone T="', ident, & + '.time step", SolutionTime=', project_sfx(ismpl) (i1+6:i2- & + 1), ', StrandID=', ident + WRITE(lout,'(1A,3(A,I5),1A)') sline(1:clast(sline)), & + ', i=', i0, ', j=', j0, ', k=', k0, ', f=point' + ELSE + WRITE(lout,'(3(A,I5),1A)') 'zone i=', i0, ', j=', j0, & + ', k=', k0, ', f=point' + END IF + +! output of box-Centred data: + dz = 0.5D0*delz(1) + DO k = 1, k0 + IF (k>1) dz = dz + 0.5D0*(delz(k-1)+delz(k)) + dy = 0.5D0*dely(1) + DO j = 1, j0 + IF (j>1) dy = dy + 0.5D0*(dely(j-1)+dely(j)) + dx = 0.5D0*delx(1) + DO i = 1, i0 + IF (i>1) dx = dx + 0.5D0*(delx(i-1)+delx(i)) + idx = i + (j-1)*i0 + (k-1)*i0*j0 + WRITE(lout,'(3(e15.6,1x),1I9,3I6,9999(e21.12,1x))') dx, & + dy, dz, uindex(i,j,k), i, j, k, & + head(i,j,k,ismpl) - headold(idx,cgen_fw,ismpl), & + temp(i,j,k,ismpl) - tempold(idx,cgen_fw,ismpl), & + (conc(i,j,k,l,ismpl)-concold(idx,l,cgen_fw,ismpl),l=1,ntrans), & + (pres(i,j,k,ismpl)-presold(idx,cgen_fw,ismpl))*pa_conv1 + END DO + END DO + END DO + + CLOSE(lout) + CALL omp_del_file_handler(lout) + CALL compress_file(compress_out,filename) + RETURN + END diff --git a/forward/output/write_tecplot.f90 b/forward/output/write_tecplot.f90 new file mode 100644 index 0000000..34c2d81 --- /dev/null +++ b/forward/output/write_tecplot.f90 @@ -0,0 +1,737 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes data in tecplot-format +!> @param[in] ident index number for file name +!> @param[in] ismpl local sample index + SUBROUTINE write_tecplot(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + INCLUDE 'OMP_TOOLS.inc' + + INTEGER i1, i2, i3, i4, i1s, i2s, ident, lblank, lout, locstr, & + clast + EXTERNAL lblank, locstr, clast + + DOUBLE PRECISION vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, & + rhof, visf + EXTERNAL vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, rhof, & + visf + DOUBLE PRECISION qxc, qyc, qzc + EXTERNAL qxc, qyc, qzc + + DOUBLE PRECISION px, py, pz + character (len=256) :: filename + character (len=20) :: snumber + character (len=1024) :: sline + + double precision, parameter :: zero = 0.0d0 + + logical :: cell_centered + integer :: line_break_cc + + IF ( .NOT. tec_out) RETURN +#ifdef NOPLT + RETURN +#endif + +! get his own file discriptor index + CALL omp_new_file_handler(lout,16) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // '_' // & + snumber(i3:i4), '"' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // & + project_sfx(ismpl) (i1s:i2s) // '_' // snumber(i3:i4), '"' + END IF + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Tecplot to "', & + filename(1:lblank(filename)), '"' + END IF + + + cell_centered = .false. + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + if(cell_centered) then + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + WRITE(lout,'(10A)') 'variables = "xnode","ynode","znode","i", "j", "k", "x", & + & "y", "z", "uindex",', & + ' "obsz","obst","cindex",', & + ' "head", "temp",', & + ' "pres",', & + ' "vx", "vy", "vz",', & + ' "por", "kx", "ky",', & + ' "kz", "lx", "ly",', & + ' "lz", "rhof", "visf",', & + ' "qxc", "qyc", "qzc",', & + ' "sigma", "lc", "src",' + + + ! DIFFERENCE FOR CELLCENTERED + i1 = locstr(project_sfx(ismpl),'_time_') + i2 = locstr(project_sfx(ismpl),'_out') + IF (i1>=1 .AND. i2>=1) THEN + WRITE(sline,'(1A,1I7,3A,1I7)') 'zone T="', ident, & + '.time step", SolutionTime=', project_sfx(ismpl) (i1+6:i2- & + 1), ', StrandID=', ident + WRITE(lout,'(1A,3(A,I5),1A)') sline(1:clast(sline)), & + ', i=', i0+1, ', j=', j0+1, ', k=', k0+1, ', f=block' + ELSE + WRITE(lout,'(3(A,I5),1A)') 'zone i=', i0+1, ', j=', j0+1, & + ', k=', k0+1, ', f=block' + END IF + + ! DIFFERENCE FOR CELLCENTERED + write(lout,*) 'VARLOCATION=([1,2,3]=NODAL,& + & [4,5,6,7,8,9,10,11,12,13,14,15,16,17& + &,18,19,20,21,22,23,24,25,26,27,28,29,& + &30,31,32,33,34,35,36,37,38,39]=CELLCENTERED)' + line_break_cc = 0 + do k = 1, k0+1 + do j = 1, j0+1 + do i = 1, i0 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delxa(i)-0.5d0*delx(i) + if(i==i0) write(unit = lout, fmt = '(g15.6,1x)', advance='no') delxa(i)+0.5d0*delx(i) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0+1 + do j = 1, j0 + do i = 1, i0+1 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delya(j)- 0.5d0*dely(j) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + if(j==j0) then + do i = 1, i0+1 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delya(j)+0.5d0*dely(j) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end if + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0+1 + do i = 1, i0+1 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delza(k)-0.5d0*delz(k) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + if(k==k0) then + do j = 1, j0+1 + do i = 1, i0+1 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delza(k)+0.5d0*delz(k) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end if + end do + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(i6)', advance='no') i + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + + line_break_cc = 0 + write(unit = lout, fmt = *) + + + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(i6)', advance='no') j + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + + line_break_cc = 0 + write(unit = lout, fmt = *) + + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(i6)', advance='no') k + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delxa(i) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + + line_break_cc = 0 + write(unit = lout, fmt = *) + + + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delya(j) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + + line_break_cc = 0 + write(unit = lout, fmt = *) + + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(g15.6,1x)', advance='no') delza(k) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(i10)', advance='no') uindex(i,j,k) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es17.8,1x)', advance='no') head(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es17.8,1x)', advance='no') temp(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es17.8,1x)', advance='no') pres(i,j,k,ismpl)*pa_conv1 + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') vxc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') vyc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') vzc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') por(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + px = kx(i,j,k,ismpl) + if(klogflag) then + px = log10(kx(i,j,k,ismpl)) + end if + write(unit = lout, fmt = '(es15.6,1x)', advance='no') px + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = *, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + py = ky(i,j,k,ismpl) + if(klogflag) then + py = log10(ky(i,j,k,ismpl)) + end if + write(unit = lout, fmt = '(es15.6,1x)', advance='no') py + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = *, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + pz = kz(i,j,k,ismpl) + if(klogflag) then + pz = log10(kz(i,j,k,ismpl)) + end if + write(unit = lout, fmt = '(es15.6,1x)', advance='no') pz + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') lx(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') ly(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') lz(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') rhof(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') visf(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') qxc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') qyc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + line_break_cc = 0 + write(unit = lout, fmt = *) + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') qzc(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + write(unit = lout, fmt = *) + write(unit = lout, fmt = *) +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + line_break_cc = 0 + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + write(unit = lout, fmt = '(es15.6,1x)', advance='no') w(i,j,k,ismpl) + ! Line break after 100 entries + line_break_cc = line_break_cc + 1 + if(line_break_cc >= 100) then + write(unit = lout, fmt = *) + line_break_cc = 0 + end if + end do + end do + end do + + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + else + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + + WRITE(lout,'(9A)') 'variables = "i", "j", "k", "x", & + & "y", "z", "uindex",', & + ' "head", "temp",', & + ' "pres",', & + ' "vx", "vy", "vz",', & + ' "por", "kx", "ky",', & + ' "kz", "lx", "ly",', & + ' "lz", "rhof", "visf",', & + ' "qxc", "qyc", "qzc",', & + ' "sigma", "lc", "src",' + + ! use sline for ZONE string + i1 = locstr(project_sfx(ismpl),'_time_') + i2 = locstr(project_sfx(ismpl),'_out') + IF (i1>=1 .AND. i2>=1) THEN +!!$ WRITE(sline,'(1A,1I7,3A,1I7)') 'zone T="', ident, & +!!$ '.time step", SolutionTime=', project_sfx(ismpl) (i1+6:i2- & +!!$ 1), ', StrandID=', 1 + WRITE(sline,'(1A,1I7)') 'zone StrandID=', 1 + WRITE(lout,'(1A,3(A,I5),1A)') sline(1:clast(sline)), & + ', i=', i0, ', j=', j0, ', k=', k0, ', f=point' + ELSE + WRITE(lout,'(3(A,I5),1A)') 'zone i=', i0, ', j=', j0, & + ', k=', k0, ', f=point' + END IF + + ! output of box-Centred data: + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + px = kx(i,j,k,ismpl) + py = ky(i,j,k,ismpl) + pz = kz(i,j,k,ismpl) + IF (klogflag) THEN + px = log10(kx(i,j,k,ismpl)) + py = log10(ky(i,j,k,ismpl)) + pz = log10(kz(i,j,k,ismpl)) + END IF + WRITE(lout, & + '(3i6,3(g15.6,1x),i10,3(e17.8,1x),19(e15.6,1x))') & + i, j, k, delxa(i), delya(j), delza(k), uindex(i,j,k), & + head(i,j,k,ismpl), temp(i,j,k,ismpl), & + pres(i,j,k,ismpl)*pa_conv1, & + vxc(i,j,k,ismpl), vyc(i,j,k,ismpl), & + vzc(i,j,k,ismpl), por(i,j,k,ismpl), px, py, pz, & + lx(i,j,k,ismpl), ly(i,j,k,ismpl), lz(i,j,k,ismpl), & + rhof(i,j,k,ismpl), visf(i,j,k,ismpl), & + qxc(i,j,k,ismpl), qyc(i,j,k,ismpl), qzc(i,j,k,ismpl), & + w(i,j,k,ismpl) + END DO + END DO + END DO + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + + end if + +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + CLOSE(lout) + CALL omp_del_file_handler(lout) + CALL compress_file(compress_out,filename) + + RETURN + END diff --git a/forward/output/write_tecplotc.f90 b/forward/output/write_tecplotc.f90 new file mode 100644 index 0000000..343e646 --- /dev/null +++ b/forward/output/write_tecplotc.f90 @@ -0,0 +1,149 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writess conc-data in tecplot-format +!> @param[in] ident index number for file name +!> @param[in] ismpl local sample index + SUBROUTINE write_tecplotc(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + INCLUDE 'OMP_TOOLS.inc' + + DOUBLE PRECISION v_abs + INTEGER i1, i2, i3, i4, i1s, i2s, ident, lblank, lout, locstr, & + clast + EXTERNAL lblank, locstr, clast + + DOUBLE PRECISION vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, & + rhof, visf + EXTERNAL vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, rhof, & + visf + DOUBLE PRECISION qxc, qyc, qzc + EXTERNAL qxc, qyc, qzc + + character (len=80) :: filename + character (len=20) :: snumber + character (len=1024) :: sline + INTRINSIC dsqrt + + + IF ( .NOT. tec_out .OR. .NOT. trans_active) RETURN +#ifdef NOPLT + RETURN +#endif + +! get his own file discriptor index + CALL omp_new_file_handler(lout,16) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // & + '_chem.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // '_' // & + snumber(i3:i4), '_chem"' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '_chem.plt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(3A)') 'title = "', project(i1:i2) // & + project_sfx(ismpl) (i1s:i2s) // '_' // snumber(i3:i4), '"' + END IF + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Tecplot to "', & + filename(1:lblank(filename)), '"' + END IF + + + WRITE(lout,'(7A,9999(1A12,1I4.4,1A1))') & + 'variables = "x", "y", "z","uindex",', & + ' "i", "j", "k", ', ' "head",', & + ' "temp",', ' "pres",', & + ' "v_abs",', & + ' "tsal"', (', "conc',i,'"',i=1,ntrans) + +! use sline for ZONE string + i1 = locstr(project_sfx(ismpl),'_time_') + i2 = locstr(project_sfx(ismpl),'_out') + IF (i1>=1 .AND. i2>=1) THEN + WRITE(sline,'(1A,1I7,3A,1I7)') 'zone T="', ident, & + '.time step", SolutionTime=', project_sfx(ismpl) (i1+6:i2- & + 1), ', StrandID=', ident + WRITE(lout,'(1A,3(A,I5),1A)') sline(1:clast(sline)), & + ', i=', i0, ', j=', j0, ', k=', k0, ', f=point' + ELSE + WRITE(lout,'(3(A,I5),1A)') 'zone i=', i0, ', j=', j0, & + ', k=', k0, ', f=point' + END IF + +! output of box-Centred data: + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + v_abs = dsqrt(vxc(i,j,k,ismpl)*vxc(i,j,k,ismpl)+ & + vyc(i,j,k,ismpl)*vyc(i,j,k,ismpl)+ & + vzc(i,j,k,ismpl)*vzc(i,j,k,ismpl)) + WRITE(lout,'(3(g15.6,1x),1I9,3I6,1X,5(e17.8,1x),9999(e17.8,1A))') & + delxa(i), delya(j), delza(k), & + uindex(i,j,k), i, j, k, & + head(i,j,k,ismpl), & + temp(i,j,k,ismpl), pres(i,j,k,ismpl)*pa_conv1, & + v_abs, tsal(i,j,k,ismpl), & + (conc(i,j,k,l,ismpl),' ',l=1,ntrans) + END DO + END DO + END DO + + CLOSE(lout) + CALL omp_del_file_handler(lout) + CALL compress_file(compress_out,filename) + + RETURN + END diff --git a/forward/output/write_text.f90 b/forward/output/write_text.f90 new file mode 100644 index 0000000..cf8ec8c --- /dev/null +++ b/forward/output/write_text.f90 @@ -0,0 +1,180 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writess data in text-format +!> @param[in] ident index/iteration number +!> @param[in] ismpl local sample index + SUBROUTINE write_text(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + + + INCLUDE 'OMP_TOOLS.inc' + + INTEGER i1, i2, i3, i4, i1s, i2s, ident, lblank, lout, tracer + EXTERNAL lblank + character (len=80) :: filename + character (len=20) :: snumber + character (len=32) :: strng + + DOUBLE PRECISION vxc, vyc, vzc + EXTERNAL vxc, vyc, vzc + + + IF ( .NOT. txt_out) RETURN +#ifdef NOTXT + RETURN +#endif + +! get his own file discriptor index + CALL omp_new_file_handler(lout,16) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '.txt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(1A)') key_char//' title' + WRITE(lout,'(1A)') project(i1:i2) // '_' // snumber(i3:i4) + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.txt' + OPEN(lout,file=filename,status='unknown',blank='null') + WRITE(lout,'(1A)') key_char//' title' + WRITE(lout,'(1A)') project(i1:i2) // & + project_sfx(ismpl) (i1s:i2s) // '_' // snumber(i3:i4) + END IF + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : Text to "', & + filename(1:lblank(filename)), '"' + END IF + +! -------- + WRITE(lout,'(1A)') key_char//' delx' + CALL write_dense3d(delx,i0,1,1,lout,ismpl) + + WRITE(lout,'(1A)') key_char//' dely' + CALL write_dense3d(dely,1,j0,1,lout,ismpl) + + WRITE(lout,'(1A)') key_char//' delz' + CALL write_dense3d(delz,1,1,k0,lout,ismpl) + +! -------- + WRITE(lout,'(1A)') key_char//' head init' + CALL write_dense3d(head(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + + WRITE(lout,'(1A)') key_char//' temp init' + CALL write_dense3d(temp(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + + DO i = 1, ntrans + WRITE(lout,'(1A,1I4.4,1A)') key_char//' tracer', i, ' init' + CALL write_dense3d(conc(1,1,1,i,ismpl),i0,j0,k0,lout,ismpl) + END DO + + WRITE(lout,'(1A)') key_char//' pres init' + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + x(i,j,k,ismpl) = pres(i,j,k,ismpl)*pa_conv1 + END DO + END DO + END DO + CALL write_dense3d(x(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + + IF (trac_active) THEN + DO tracer = 1, ntrac + WRITE(strng,'(1A,1I4.4)') 'tracer', tracer + CALL chln(strng,i1,i2) + WRITE(lout,'(3A)') key_char//' ', strng(i1:i2), ' init' + CALL write_dense3d(conc(1,1,1,tracer,ismpl),i0,j0,k0,lout, & + ismpl) + END DO + END IF + +! -------- + WRITE(lout,'(1A)') key_char//' vx init' + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + x(i,j,k,ismpl) = vxc(i,j,k,ismpl) + END DO + END DO + END DO + CALL write_dense3d(x(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + + WRITE(lout,'(1A)') key_char//' vy init' + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + x(i,j,k,ismpl) = vyc(i,j,k,ismpl) + END DO + END DO + END DO + CALL write_dense3d(x(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + + WRITE(lout,'(1A)') key_char//' vz init' + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + x(i,j,k,ismpl) = vzc(i,j,k,ismpl) + END DO + END DO + END DO + CALL write_dense3d(x(1,1,1,ismpl),i0,j0,k0,lout,ismpl) + +! -------- + CLOSE(lout) + CALL omp_del_file_handler(lout) + CALL compress_file(compress_out,filename) + + RETURN + END diff --git a/forward/output/write_vtk.f90 b/forward/output/write_vtk.f90 new file mode 100644 index 0000000..41ae772 --- /dev/null +++ b/forward/output/write_vtk.f90 @@ -0,0 +1,307 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes data in vtk-format +!> @param[in] ident output file index number +!> @param[in] ismpl local sample index +!> @details +!>writes data in vtk-format \n +!>see: http://mayavi.sourceforge.net\n +!> http://www.vtk.org/pdf/file-formats.pdf\n + SUBROUTINE write_vtk(ident,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_data + use mod_time + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + + + INCLUDE 'OMP_TOOLS.inc' + + DOUBLE PRECISION, ALLOCATABLE :: val(:) + ! DOUBLE PRECISION dx, dy, dz + INTEGER i1s, i2s, i1, i2, i3, i4, species, ident, lblank, lout + EXTERNAL lblank + + DOUBLE PRECISION vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, & + qt, rhof,visf, visn + EXTERNAL vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, qt, rhof, & + visf, visn + + DOUBLE PRECISION qxc, qyc, qzc + EXTERNAL qxc, qyc, qzc + + character (len=20) :: snumber + character (len=256) :: filename, prname, strng + + + IF ( .NOT. vtk_out) RETURN +#ifdef NOVTK + RETURN +#endif + +! get his own file discriptor index + CALL omp_new_file_handler(lout,16) + + ALLOCATE(val(max(i0,j0,k0))) + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A20)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A20)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A20)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A20)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A20)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + + IF (i1s==0) THEN + prname = project(i1:i2) // '_' // snumber(i3:i4) + filename = project(i1:i2) // '_' // snumber(i3:i4) // '.vtk' + ELSE + prname = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.vtk' + END IF + + OPEN(lout,file=filename,status='unknown',blank='null') + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : VTK to "', & + filename(1:lblank(filename)), '"' + END IF + +! HEADER + WRITE(lout,'(a/a/a/a/a,3I7)') '# vtk DataFile Version 2.0', & + prname, 'ASCII', 'DATASET RECTILINEAR_GRID', 'DIMENSIONS ', & + i0, j0, k0 + !i0+1, j0+1, k0 + + +! X_COORDINATES + WRITE(lout,'(a,I7,a)') 'X_COORDINATES ', i0, ' float' + val(1) = 0.5D0*delx(1) + DO i = 2, i0 + val(i) = val(i-1) + 0.5D0*(delx(i-1)+delx(i)) + END DO + WRITE(lout,'(100e16.6)') (val(i),i=1,i0) + + !WRITE(lout,'(a,I7,a)') 'X_COORDINATES ', i0+1, ' float' + !WRITE(lout,'(100e16.6)') (delxa(i)-0.5d0*delx(i),i=1,i0) + !write(unit = lout, fmt = '(e16.6)') delxa(i0) + 0.5d0*delx(i0) + +! Y_COORDINATES + WRITE(lout,'(a,I7,a)') 'Y_COORDINATES ', j0, ' float' + val(1) = 0.5D0*dely(1) + DO i = 2, j0 + val(i) = val(i-1) + 0.5D0*(dely(i-1)+dely(i)) + END DO + WRITE(lout,'(100e16.6)') (val(i),i=1,j0) + + !WRITE(lout,'(a,I7,a)') 'Y_COORDINATES ', j0+1, ' float' + !WRITE(lout,'(100e16.6)') (delya(i)-0.5d0*dely(i),i=1,j0) + !write(unit = lout, fmt = '(e16.6)') delya(j0) + 0.5d0*dely(j0) + + +! Z_COORDINATES + WRITE(lout,'(a,I7,a)') 'Z_COORDINATES ', k0, ' float' + val(1) = 0.5D0*delz(1) + DO i = 2, k0 + val(i) = val(i-1) + 0.5D0*(delz(i-1)+delz(i)) + END DO + WRITE(lout,'(100e16.6)') (val(i),i=1,k0) + + !WRITE(lout,'(a,I7,a)') 'Z_COORDINATES ', k0+1, ' float' + !WRITE(lout,'(100e16.6)') (delza(i)-0.5d0*delz(i),i=1,k0) + !write(unit = lout, fmt = '(e16.6)') delza(k0) + 0.5d0*delz(k0) + + !WRITE(lout,'(a,I7,a)') 'Z_COORDINATES ', k0, ' float' + !write(unit = lout, fmt = '(100e16.6)') (delza(i),i=1,k0) + + + WRITE(lout,'(/a,i8)') 'POINT_DATA', i0*j0*k0 + !WRITE(lout,'(/a,i8)') 'CELL_DATA', i0*j0*k0 + + + if(out_ijk(cout_uindex)) then + WRITE(lout,'(a)') 'SCALARS uindex int 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(25I10)') (((uindex(i,j,k),i=1,i0),j=1,j0),k=1,k0) + end if + + if(out_prop(idx_por)) then + WRITE(lout,'(a)') 'SCALARS por float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((por(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + + IF (temp_active) THEN + if(out_pv(pv_temp)) then + WRITE(lout,'(a)') 'SCALARS temp float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((temp(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_an_lx)) then + WRITE(lout,'(a)') 'SCALARS lx float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((lx(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_an_ly)) then + WRITE(lout,'(a)') 'SCALARS ly float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((ly(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_lz)) then + WRITE(lout,'(a)') 'SCALARS lz float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((lz(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_q)) then + WRITE(lout,'(a)') 'VECTORS q float' + WRITE(lout,'(3e16.6)') (((qxc(i,j,k,ismpl),qyc(i,j,k,ismpl),qzc(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + WRITE(lout,'(a)') 'SCALARS h float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((qt(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + END IF + + IF (head_active) THEN + if(out_pv(pv_head)) then + WRITE(lout,'(a)') 'SCALARS head float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((head(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) + end if + END IF + IF (pres_active) THEN + if(out_pv(pv_pres)) then + WRITE(lout,'(a)') 'SCALARS pres float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((pres(i,j,k,ismpl)*pa_conv1,i=1,i0),j=1,j0),k=1,k0) +#ifdef pres_base + CALL pres2head(1,ismpl) + WRITE(lout,'(a)') 'SCALARS head float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((head(i,j,k,ismpl),i=1,i0),j=1,j0),k=1,k0) +#endif + end if + END IF + + IF (head_active .OR. pres_active) THEN + IF (klogflag) THEN + if(out_prop(idx_an_kx)) then + WRITE(lout,'(a)') 'SCALARS kx float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((log10(kx(i,j,k,ismpl)),i=1, & + i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_an_ky)) then + WRITE(lout,'(a)') 'SCALARS ky float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((log10(ky(i,j,k,ismpl)),i=1, & + i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_kz)) then + WRITE(lout,'(a)') 'SCALARS kz float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((log10(kz(i,j,k,ismpl)),i=1, & + i0),j=1,j0),k=1,k0) + end if + if(out_ijk(cout_rhof)) then + WRITE(lout,'(a)') 'SCALARS rhof float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((rhof(i,j,k,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + end if + ELSE + if(out_prop(idx_an_kx)) then + WRITE(lout,'(a)') 'SCALARS kx float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((kx(i,j,k,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_an_ky)) then + WRITE(lout,'(a)') 'SCALARS ky float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((ky(i,j,k,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + end if + if(out_prop(idx_kz)) then + WRITE(lout,'(a)') 'SCALARS kz float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((kz(i,j,k,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + end if + END IF + ! WRITE(lout,'(a)') 'VECTORS v float' + ! WRITE(lout,'(3e16.6)') (((vxc(i,j,k,ismpl), & + ! vyc(i,j,k,ismpl),vzc(i,j,k,ismpl),i=1, & + ! i0),j=1,j0),k=1,k0) + END IF + + IF (trac_active) THEN + if(out_pv(pv_conc)) then + DO species = 1, ntrans + WRITE(strng,'(I7)') species + CALL chln(strng,i1,i2) + WRITE(lout,'(a)') 'SCALARS tracer' // strng(i1:i2) // ' float 1' + WRITE(lout,'(a)') 'LOOKUP_TABLE default' + WRITE(lout,'(100e16.6)') (((conc(i,j,k,species,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + END DO + end if + END IF + + !Supposed to be written behind tracer output + IF (head_active .OR. pres_active) THEN + WRITE(lout,'(a)') 'VECTORS v float' + WRITE(lout,'(3e16.6)') (((vxc(i,j,k,ismpl), & + vyc(i,j,k,ismpl),vzc(i,j,k,ismpl),i=1, & + i0),j=1,j0),k=1,k0) + END IF + + DEALLOCATE(val) + + CLOSE(lout) + CALL omp_del_file_handler(lout) + CALL compress_file(compress_out,filename) + + RETURN + END diff --git a/forward/pres/calc_pres.f90 b/forward/pres/calc_pres.f90 new file mode 100644 index 0000000..de5e0c2 --- /dev/null +++ b/forward/pres/calc_pres.f90 @@ -0,0 +1,86 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief top level routine for setup and computing pressure flow +!> @param[in] ismpl local sample index + SUBROUTINE calc_pres(ismpl) + use arrays + use mod_genrlc + use mod_genrl + use mod_flow + use mod_time + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i + INCLUDE 'OMP_TOOLS.inc' + INTEGER ijk + + + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_pres' +! +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + + ijk = i0*j0*k0 +! default to mark a non-boundary +!$OMP master + DO i = 1, ijk + bc_mask(i,ismpl) = '+' + END DO +!$OMP end master +! initialize coefficients for sparse solvers + CALL omp_set_dval(ijk,0.D0,a(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,b(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,c(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,d(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,e(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,f(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,g(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,w(1,1,1,ismpl)) + +!$OMP barrier +! calculate coefficients + CALL set_pcoef(ismpl) +! set fluid sources/sinks + CALL set_pq(ismpl) + +!$OMP barrier + CALL set_pcoefrs(ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + +! set boundary conditions + CALL set_pbc(ismpl) + + IF (linfos(3)>=2) WRITE(*,*) ' ... solve(pres)' + +! solve it + CALL solve(pv_pres,-1,pres(1,1,1,ismpl),errf,aparf,controlf, & + ismpl) + + RETURN + END diff --git a/forward/pres/neumann_pres.f90 b/forward/pres/neumann_pres.f90 new file mode 100644 index 0000000..6873ea4 --- /dev/null +++ b/forward/pres/neumann_pres.f90 @@ -0,0 +1,203 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_neumann_pres" +!> @param[out] neumann_max neumann criteria +!> @param[in] ismpl local sample index + SUBROUTINE neumann_pres(neumann_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION neumann_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_neumann_pres(neumann_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate grid neuman numbers (pres) +!> @param[out] neumann_max maximal neuman number +!> @param[in] ismpl local sample index + SUBROUTINE omp_neumann_pres(neumann_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + INTEGER c1, c2, c3 + DOUBLE PRECISION neumann_maxx, neumann_minx, neumann_avgx, & + neumann_maxy, neumann_miny, neumann_avgy, neumann_maxz, & + neumann_minz, neumann_avgz, neumann_x, neumann_y, neumann_z, & + val, neumann_max, delt, fac, davg + DOUBLE PRECISION deltat + EXTERNAL deltat + DOUBLE PRECISION fi, fj, fk, rhof, visf, por, compf, compm, & + pstor + EXTERNAL fi, fj, fk, rhof, visf, por, compf, compm, pstor + + + delt = deltat(simtime(ismpl),ismpl) + + IF ( .NOT. (transient .AND. tr_switch(ismpl))) THEN +!$OMP master + WRITE(*,*) ' neumann-pres: not defined for steady state' +!$OMP end master + RETURN + ELSE IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... neumann-pres: delt/tunit = ', & + delt/tunit + WRITE(*,*) +!$OMP end master + END IF + + +! val in x + c1 = 0 + neumann_maxx = small + neumann_minx = big + neumann_avgx = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + fac = delt/pstor(i,j,k,ismpl) + val = fac*fi(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxx) neumann_maxx = val + IF (val<neumann_minx) neumann_minx = val + neumann_avgx = neumann_avgx + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in y + c2 = 0 + neumann_maxy = small + neumann_miny = big + neumann_avgy = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + fac = delt/pstor(i,j,k,ismpl) + val = fac*fj(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxy) neumann_maxy = val + IF (val<neumann_miny) neumann_miny = val + neumann_avgy = neumann_avgy + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in z + c3 = 0 + neumann_maxz = small + neumann_minz = big + neumann_avgz = 0.0D0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + fac = delt/pstor(i,j,k,ismpl) + val = fac*fk(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxz) neumann_maxz = val + IF (val<neumann_minz) neumann_minz = val + neumann_avgz = neumann_avgz + val + END DO + END DO + END DO +!$OMP end do nowait + +! compute global sum for all values + CALL omp_summe(neumann_maxx,neumann_minx,neumann_avgx, & + neumann_maxy,neumann_miny,neumann_avgy,neumann_maxz, & + neumann_minz,neumann_avgz,c1,c2,c3,ismpl) + +!$OMP master + IF (i0>2) THEN + neumann_avgx = neumann_avgx/dble(c1) + ELSE + neumann_maxx = 0.0D0 + neumann_minx = 0.0D0 + neumann_avgx = 0.0D0 + END IF + IF (j0>2) THEN + neumann_avgy = neumann_avgy/dble(c2) + ELSE + neumann_maxy = 0.0D0 + neumann_miny = 0.0D0 + neumann_avgy = 0.0D0 + END IF + IF (k0>2) THEN + neumann_avgz = neumann_avgz/dble(c3) + ELSE + neumann_maxz = 0.0D0 + neumann_minz = 0.0D0 + neumann_avgz = 0.0D0 + END IF + + neumann_max = max(neumann_maxx,neumann_maxy,neumann_maxz) + + IF (linfos(3)>=2) THEN + WRITE(*,*) 'neumann number for pres in x,y,z:' + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' max. : ', & + neumann_maxx, ', ', neumann_maxy, ', ', neumann_maxz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' min. : ', & + neumann_minx, ', ', neumann_miny, ', ', neumann_minz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + neumann_avgx, ', ', neumann_avgy, ', ', neumann_avgz + END IF + + IF (linfos(3)>=1 .AND. neumann_max>0.5D0) THEN + WRITE(*,'(a)') '!!!: neumann pres greater than 1/2 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + neumann_maxx, 'y: ', neumann_maxy, 'z: ', neumann_maxz + WRITE(*,*) + END IF +!$OMP end master + + RETURN + END diff --git a/forward/pres/omp_pres2head.f90 b/forward/pres/omp_pres2head.f90 new file mode 100644 index 0000000..8659b00 --- /dev/null +++ b/forward/pres/omp_pres2head.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief head setup +!> @param[in] init flag: 0-init, 1-normal setup +!> @param[in] ismpl local sample index +!> @details +!> head setup currently disabled\n + SUBROUTINE omp_pres2head(init,ismpl) + use arrays + use mod_flow + use mod_genrl + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + INCLUDE 'OMP_TOOLS.inc' + INTEGER init + DOUBLE PRECISION psurf + +! presetting for dirichlet boundary conditions to avoid site effects + IF (pres_active) THEN + CALL set_dpbc(ismpl) + CALL set_dtbc(ismpl) + psurf = 1.0D5 +!$OMP barrier +! +!$OMP do schedule(static) collapse(3) + DO i = 1, i0 + DO j = 1, j0 + DO k = 1, k0 + head(i,j,k,ismpl) = (pres(i,j,k,ismpl) - psurf)/(rref*grav) + delza(k) + END DO + END DO + END DO +!$OMP end do nowait + END IF +! + RETURN + END diff --git a/forward/pres/pbuoy.f90 b/forward/pres/pbuoy.f90 new file mode 100644 index 0000000..4e8b924 --- /dev/null +++ b/forward/pres/pbuoy.f90 @@ -0,0 +1,105 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate buoyancy for pressure equation +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return buoyancy for pressure +!> @details +!> calculate buoyancy for pressure equation\n +!> sign convention: negative for positive buoyancy\n +!> if porosity is 1.E-20, the pressure is set to\ +!> atmospheric pressure + DOUBLE PRECISION FUNCTION buoy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION rhav, hh, h0, h1, prod, summ + DOUBLE PRECISION rhof, kz, visf, por, rh1, rh2 + EXTERNAL rhof, kz, visf, por + + buoy = 0.D0 + IF (por(i,j,k,ismpl).LT.1.E-19) THEN + rh1 = 1.29E0 + ELSE + rh1 = rhof(i,j,k,ismpl) + END IF + IF (por(i,j,k+1,ismpl).LT.1.E-19) THEN + rh2 = 1.29E0 + ELSE + rh2 = rhof(i,j,k+1,ismpl) + END IF + rhav = 0.5D0*(rh1+rh2) + + hh = 0.D0 + h0 = kz(i,j,k,ismpl)/visf(i,j,k,ismpl) + h1 = kz(i,j,k+1,ismpl)/visf(i,j,k+1,ismpl) + summ = h0 + h1 + prod = h0*h1 + IF (summ>0.D0) hh = 2.0D0*prod/summ + + buoy = hh*grav*rhav + + RETURN + END + +!> @brief calculate buoyancy for pressure equation +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return buoyancy for pressure +!> @details +!> calculate buoyancy for pressure equation\n +!> sign convention: negative for positive buoyancy\n + DOUBLE PRECISION FUNCTION vbuoy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION h0, h1, prod, summ + DOUBLE PRECISION rhof, kz, visf, rhav, por + EXTERNAL rhof, kz, visf, por + + rhav = 0.5D0*(rhof(i,j,k+1,ismpl)+rhof(i,j,k,ismpl)) + vbuoy = 0.D0 + h0 = kz(i,j,k,ismpl)*rhof(i,j,k,ismpl)/visf(i,j,k,ismpl) + h1 = kz(i,j,k+1,ismpl)*rhof(i,j,k+1,ismpl)/visf(i,j,k+1,ismpl) + summ = h0 + h1 + prod = h0*h1 + IF (summ>0.D0) vbuoy = 2.0D0*prod/summ + IF (por(i,j,k,ismpl).LT.1.E-19) vbuoy = 1.29E-8/998. + + vbuoy = vbuoy*grav +! IF (por(i,j,k,ismpl).LT.1.E-19) vbuoy = 0. + + RETURN + END diff --git a/forward/pres/pfluxes.f90 b/forward/pres/pfluxes.f90 new file mode 100644 index 0000000..1faa93b --- /dev/null +++ b/forward/pres/pfluxes.f90 @@ -0,0 +1,365 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vx(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION f1, f2, dif, gi + EXTERNAL gi + + vx = 0.D0 + IF (i0>1 .AND. i<i0) THEN + dif = pres(i+1,j,k,ismpl) - pres(i,j,k,ismpl) + vx = -gi(i,j,k,ismpl)*dif + END IF + RETURN + END + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, dif, gj + EXTERNAL gj + + vy = 0.D0 + IF (j0>1 .AND. j<j0) THEN + dif = pres(i,j+1,k,ismpl) - pres(i,j,k,ismpl) + vy = -gj(i,j,k,ismpl)*dif + END IF + RETURN + END + +!> @brief calculate velocities at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vz(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, dif, gk, vbuoy, por, rhof, rhav + EXTERNAL gk, rhof, por + + vz = 0.D0 + IF (k0>1 .AND. k<k0) THEN +! rhav = 0.5D0*(rhof(i,j,k+1,ismpl)+rhof(i,j,k,ismpl))& +! *(delza(k+1 )-delza(k)) + dif = pres(i,j,k+1,ismpl) - pres(i,j,k,ismpl) + IF (por(i,j,k,ismpl).GT.1.E-19) THEN + rhav = rhof(i,j,k,ismpl) + ELSE + rhav = 1.29E0 + END IF + IF (por(i,j,k+1,ismpl).GT.1.E-19) THEN + rhav = rhav + rhof(i,j,k+1,ismpl) + ELSE + rhav = rhav + 1.29E0 + END IF + rhav = 0.5*rhav*(delza(k+1 )-delza(k)) + dif = dif + rhav*grav + vz = -gk(i,j,k,ismpl)*dif! - vbuoy(i,j,k,ismpl) + END IF + + RETURN + END + +!> @brief calculate x-velocities at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vxc(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION vx, amean + EXTERNAL vx, amean + + vxc = 0.D0 + IF (i0<=1) RETURN + IF (i>1 .AND. i<i0) THEN + vxc = amean(vx(i,j,k,ismpl),vx(i-1,j,k,ismpl)) + ELSE IF (i==1) THEN + vxc = vx(i,j,k,ismpl) + ELSE IF (i==i0) THEN + vxc = vx(i-1,j,k,ismpl) + END IF + RETURN + END + +!> @brief calculate y-velocities at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vyc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION vy, amean + EXTERNAL vy, amean + + vyc = 0.D0 + IF (j0<=1) RETURN + IF (j>1 .AND. j<j0) THEN + vyc = amean(vy(i,j,k,ismpl),vy(i,j-1,k,ismpl)) + ELSE IF (j==1) THEN + vyc = vy(i,j,k,ismpl) + ELSE IF (j==j0) THEN + vyc = vy(i,j-1,k,ismpl) + END IF + RETURN + END + +!> @brief calculate z-velocities at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z velocity (m/(Pa s)) + DOUBLE PRECISION FUNCTION vzc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION vz, amean + EXTERNAL vz, amean + + vzc = 0.D0 + IF (k0<=1) RETURN + IF (k>1 .AND. k<k0) THEN + vzc = amean(vz(i,j,k,ismpl),vz(i,j,k-1,ismpl)) + ELSE IF (k==1) THEN + vzc = vz(i,j,k,ismpl) + ELSE IF (k==k0) THEN + vzc = vz(i,j,k-1,ismpl) + END IF + RETURN + END + +!> @brief average conductivities on cell faces in x direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION fi(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kx, rhof, visf + EXTERNAL kx, rhof, visf + + fi = 0.D0 + IF (i0>1 .AND. i<i0) THEN + f1 = kx(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = kx(i+1,j,k,ismpl)/ & + visf(i+1,j,k,ismpl) + prod = f1*f2 + summ = f1*delx(i+1) + f2*delx(i) + IF (summ>0.D0) fi = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average conductivities on cell faces in y direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION fj(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, ky, rhof, visf + EXTERNAL ky, rhof, visf + + fj = 0.D0 + IF (j0>1 .AND. j<j0) THEN + f1 = ky(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = ky(i,j+1,k,ismpl)/ & + visf(i,j+1,k,ismpl) + prod = f1*f2 + summ = f1*dely(j+1) + f2*dely(j) + IF (summ>0.D0) fj = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average conductivities on cell faces in z direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION fk(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kz, rhof, visf + EXTERNAL kz, rhof, visf + + fk = 0.D0 + IF (k0>1 .AND. k<k0) THEN + f1 = kz(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = kz(i,j,k+1,ismpl)/ & + visf(i,j,k+1,ismpl) + prod = f1*f2 + summ = f1*delz(k+1) + f2*delz(k) + IF (summ>0.D0) fk = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average conductivities on cell faces in x direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION gi(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kx, rhof, visf + EXTERNAL kx, rhof, visf + + gi = 0.D0 + IF (i0>1 .AND. i<i0) THEN + f1 = kx(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = kx(i+1,j,k,ismpl)/visf(i+1,j,k,ismpl) + prod = f1*f2 + summ = f1*delx(i+1) + f2*delx(i) + IF (summ>0.D0) gi = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average conductivities on cell faces in y direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION gj(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, ky, rhof, visf + EXTERNAL ky, rhof, visf + + gj = 0.D0 + IF (j0>1 .AND. j<j0) THEN + f1 = ky(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = ky(i,j+1,k,ismpl)/visf(i,j+1,k,ismpl) + prod = f1*f2 + summ = f1*dely(j+1) + f2*dely(j) + IF (summ>0.D0) gj = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average conductivities on cell faces in z direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z conductivity (m/(Pa s)) + DOUBLE PRECISION FUNCTION gk(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_flow + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, kz, rhof, visf + EXTERNAL kz, rhof, visf + + gk = 0.D0 + IF (k0>1 .AND. k<k0) THEN + f1 = kz(i,j,k,ismpl)/visf(i,j,k,ismpl) + f2 = kz(i,j,k+1,ismpl)/visf(i,j,k+1,ismpl) + prod = f1*f2 + summ = f1*delz(k+1) + f2*delz(k) + IF (summ>0.D0) gk = 2.D0*prod/summ + END IF + RETURN + END diff --git a/forward/pres/pres2head.f90 b/forward/pres/pres2head.f90 new file mode 100644 index 0000000..50cc336 --- /dev/null +++ b/forward/pres/pres2head.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute hydraulic head from pressure +!> @param[in] init flag: 0-init, 1-normal setup +!> @param[in] ismpl local sample index +!> @details +!> parallelisation wrapper for hydraulic head computation + SUBROUTINE pres2head(init,ismpl) + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + INTEGER init + + IF (linfos(3)>=2) WRITE(*,'(A,I1,A)') & + ' ... hydraulic head (init=', init, ')' +! +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif +! + CALL omp_pres2head(init,ismpl) +! +#ifdef fOMP +!$OMP end parallel +#endif +! + RETURN + END diff --git a/forward/pres/pstor.f90 b/forward/pres/pstor.f90 new file mode 100644 index 0000000..a57ea2b --- /dev/null +++ b/forward/pres/pstor.f90 @@ -0,0 +1,44 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates the bulk storativity +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return bulk storativity +!> @details +!> storb(i,j,k,ismpl) calculates the bulk storativity \n +!> at node(i,j,k).\n + DOUBLE PRECISION FUNCTION pstor(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION rhof, compm, compf, por + EXTERNAL rhof, compm, compf, por + + pstor = rhof(i,j,k,ismpl)*(compm(i,j,k,ismpl)+por(i,j,k,ismpl) & + *compf(i,j,k,ismpl)) + RETURN + END diff --git a/forward/pres/set_pbc.f90 b/forward/pres/set_pbc.f90 new file mode 100644 index 0000000..e918669 --- /dev/null +++ b/forward/pres/set_pbc.f90 @@ -0,0 +1,218 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the head equation according to the boundary +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the head equation according to the boundary conditions\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_pbc(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype, i_dir + DOUBLE PRECISION val, malfa, mbeta + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +!aw i_dir = ibc_data(ib,cbc_dir) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*val +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = val + pres(i,j,k,ismpl) = val +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! neumann nodes - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) + i_dir = ibc_data(ib,cbc_dir) +! "neumann"?, skip otherwise + IF (bctype==bt_neum) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF +! + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN + IF ((i_dir==0)) val = val/(delx(i)*dely(j)*delz(k)) + IF ((i_dir==1) .OR. (i_dir==2)) val = val/delx(i) + IF ((i_dir==3) .OR. (i_dir==4)) val = val/dely(j) + IF ((i_dir==5) .OR. (i_dir==6)) val = val/delz(k) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - val + END IF + END IF +! WELLMODEL + IF (bctype==bt_neuw) THEN +! discrete values + val = dbc_data(ib,1,ismpl) +! + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN + IF (i_dir/=0) THEN + WRITE(*,'(1A,3I7,1A)') & + 'error: well function has to be defined by volume (no direction); i,j,k=[',i,j,k,']!' + STOP + END IF + val = val/(delx(i)*dely(j)*delz(k)) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - val + END IF + END IF +! + END DO + + RETURN + END + +!> @brief modify pres for the head equation according to the boundary +!> @param[in] ismpl local sample index +!> @details +!> modify PRES for the pres equation according to the boundary conditions\n + SUBROUTINE set_dpbc(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype + DOUBLE PRECISION val, malfa, mbeta + INTRINSIC max + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) pres(i,j,k,ismpl) = val + +!ae WRITE(*,'(6i4,4x,5g16.7)') i, j, k, bcu, tpbcu, bctype, & +! val + END IF + END DO +!$OMP end do nowait +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + RETURN + END diff --git a/forward/pres/set_pcoef.f90 b/forward/pres/set_pcoef.f90 new file mode 100644 index 0000000..6118d96 --- /dev/null +++ b/forward/pres/set_pcoef.f90 @@ -0,0 +1,166 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate coefficents for the head equation +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the head equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_pcoef(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + DOUBLE PRECISION fi, fj, fk + EXTERNAL fi, fj, fk + + +!$OMP master + IF (linfos(3)>=2) WRITE(*,*) ' ... fcoef' +!$OMP end master + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + + IF (i0>1) THEN + IF (i<i0) THEN + e(i,j,k,ismpl) = fi(i,j,k,ismpl)/delx(i) + END IF + IF (i>1) THEN + c(i,j,k,ismpl) = fi(i-1,j,k,ismpl)/delx(i) + END IF + END IF + + IF (j0>1) THEN + IF (j<j0) THEN + f(i,j,k,ismpl) = fj(i,j,k,ismpl)/dely(j) + END IF + IF (j>1) THEN + b(i,j,k,ismpl) = fj(i,j-1,k,ismpl)/dely(j) + END IF + END IF + + IF (k0>1) THEN + IF (k<k0) THEN + g(i,j,k,ismpl) = fk(i,j,k,ismpl)/delz(k) + END IF + IF (k>1) THEN + a(i,j,k,ismpl) = fk(i,j,k-1,ismpl)/delz(k) + END IF + END IF + + d(i,j,k,ismpl) = -(e(i,j,k,ismpl)+c(i,j,k,ismpl)+f(i,j,k & + ,ismpl)+b(i,j,k,ismpl)+g(i,j,k,ismpl)+a(i,j,k,ismpl)) + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END + +!> @brief calculate right hand side for the head equation +!> @param[in] ismpl local sample index +!> @details +!> calculate right hand side for the head equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_pcoefrs(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + DOUBLE PRECISION src, deltf, sijk + DOUBLE PRECISION buoy, compf, compm, rhof, por, deltat, pstor, & + visf + EXTERNAL buoy, compf, compm, rhof, por, deltat, pstor, visf + + deltf = deltat(simtime(ismpl),ismpl) +! rhs: sources + IF (transient .AND. tr_switch(ismpl)) THEN +! - - - - - - - - transient - - - - - - - - - - - + CALL omp_mvp(i0,j0,k0,presold(1,cgen_time,ismpl), & + x(1,1,1,ismpl),a(1,1,1,ismpl),b(1,1,1,ismpl), & + c(1,1,1,ismpl),d(1,1,1,ismpl),e(1,1,1,ismpl), & + f(1,1,1,ismpl),g(1,1,1,ismpl)) + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + src = 0.0D0 +! buoyancy + IF (k<k0) src = src + buoy(i,j,k,ismpl)/delz(k) + !IF (k.eq.k0) src = src + buoy(i,j,k-1,ismpl)/delz(k) + IF (k>1) src = src - buoy(i,j,k-1,ismpl)/delz(k) + !IF (k.eq.1) src = src - buoy(i,j,k,ismpl)/delz(k) + + sijk = pstor(i,j,k,ismpl) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - sijk/(deltf*thetaf) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + (1.0D0-thetaf)*x(i,j,k,ismpl) - & + sijk*presold(i+(j-1)*i0+(k-1)*i0*j0,cgen_time,ismpl) & + /deltf - src + w(i,j,k,ismpl) = w(i,j,k,ismpl)/thetaf + END DO + END DO + END DO +!$OMP end do nowait + + ELSE +! - - - - - - - - steady state - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + src = 0.0D0 +! buoyancy - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + IF (k<k0) src = src + buoy(i,j,k,ismpl)/delz(k) + !IF (k.eq.k0) src = src + buoy(i,j,k-1,ismpl)/delz(k) + IF (k>1) src = src - buoy(i,j,k-1,ismpl)/delz(k) + !IF (k.eq.1) src = src - buoy(i,j,k,ismpl)/delz(k) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - src + END DO + END DO + END DO +!$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/pres/set_pq.f90 b/forward/pres/set_pq.f90 new file mode 100644 index 0000000..0ad01b5 --- /dev/null +++ b/forward/pres/set_pq.f90 @@ -0,0 +1,64 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the pres equation according to the prescribed sources and sinks +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the pres equation according to the prescribed sources and sinks\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_pq(ismpl) + use arrays + use mod_genrl + use mod_time + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION deltat, deltf, qf + EXTERNAL deltat, qf + +! rhs: sources + IF (transient .AND. tr_switch(ismpl)) THEN + deltf = deltat(simtime(ismpl),ismpl) +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qf(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + ELSE +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qf(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + END IF +! + RETURN + END diff --git a/forward/save_data.f90 b/forward/save_data.f90 new file mode 100644 index 0000000..329354b --- /dev/null +++ b/forward/save_data.f90 @@ -0,0 +1,152 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief Save simulated variable values for later comparison with input data +!> @param[in] ismpl local sample index +!> @details +!> Set the values of sdata from computed (example: head) and old +!> variable arrays (example: headold). \n +!> sdata will be compared to the read in values in ddata. \n\n +!> +!> Two linear interpolations of the values are implemented:\n +!> 1. A linear interpolation of the position of the data (px,py,pz) +!> inside the grid +!> 2. according to how the time specified for the data +!> (ddata(l,cdd_time)) is located between the previous simulation +!> time (simtime(ismpl)) and the current simulation time +!> (simtime(ismpl)+deltt). \n\n +!> +!> collect and save the computed values for a comparison with +!> 'ddata(:,cid_pv)'\n +!> -> usage in 'write_data.f' and 'forward/j_*-array(inversion)'\n + SUBROUTINE save_data(ismpl) + + use arrays + use mod_genrl + use mod_data + use mod_time + use mod_linfos + + IMPLICIT NONE + + integer :: ismpl + integer :: i, j, k, l + + DOUBLE PRECISION deltt, deltat, numdiff, dalfa, dbeta, interpolatelin, bhpr + DOUBLE PRECISION px, py, pz, vals, vals_old + + INTEGER i_type, i_si + + EXTERNAL deltat, interpolatelin, bhpr + + ! get current time step, set 1.0d0 for steady state + deltt = deltat(simtime(ismpl),ismpl) + IF ( .NOT. transient) deltt = 1.D0 + +! allowed numerical difference + numdiff = 1.0D2*const_dble(1)*simtime(ismpl) +! + DO l = 1, ndata + +! correct time interval, or steady-state + IF (ddata(l,cdd_time)>simtime(ismpl)+numdiff .AND. & + ddata(l,cdd_time)<=simtime(ismpl)+deltt+numdiff .OR. & + .NOT. transient) THEN + + i = idata(l,cid_i) + j = idata(l,cid_j) + k = idata(l,cid_k) + px = ddata(l,cdd_i) + py = ddata(l,cdd_j) + pz = ddata(l,cdd_k) + + i_type = idata(l,cid_pv) + i_si = idata(l,cid_si) + +! interpolation: m=(a*n+b*o)/(a+b) + dalfa = ddata(l,cdd_time) - simtime(ismpl) + dbeta = deltt - dalfa + IF ( .NOT. transient) THEN + dalfa = 1.D0 + dbeta = 0.D0 + END IF + + vals = 0.0D0 + vals_old = 0.0D0 + +! choose physical value to save + IF (i_type==pv_head) THEN + + vals = interpolatelin(i0,j0,k0, i,j,k, & + head(1,1,1,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + vals_old = interpolatelin(i0,j0,k0, i,j,k, & + headold(1,cgen_time,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + ELSE IF (i_type==pv_pres) THEN + + vals = interpolatelin(i0,j0,k0, i,j,k, & + pres(1,1,1,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + vals_old = interpolatelin(i0,j0,k0, i,j,k, & + presold(1,cgen_time,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + ELSE IF (i_type==pv_temp) THEN + + vals = interpolatelin(i0,j0,k0, i,j,k, & + temp(1,1,1,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + vals_old = interpolatelin(i0,j0,k0, i,j,k, & + tempold(1,cgen_time,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + ELSE IF (i_type==pv_conc) THEN + + vals = interpolatelin(i0,j0,k0, i,j,k, & + conc(1,1,1,i_si,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + vals_old = interpolatelin(i0,j0,k0, i,j,k, & + concold(1,i_si,cgen_time,ismpl), & + px,py,pz, delx,dely,delz, delxa,delya,delza) + + ELSE IF (i_type==pv_bhpr) THEN + + vals = bhpr(i,j,k,ismpl) + vals_old = vals + + END IF + + ! Write time-interpolated value to sdata + sdata(l,ismpl) = (dalfa*vals+dbeta*vals_old)/deltt + + END IF + + END DO + + RETURN + END diff --git a/forward/set_tsal.f90 b/forward/set_tsal.f90 new file mode 100644 index 0000000..62dc15f --- /dev/null +++ b/forward/set_tsal.f90 @@ -0,0 +1,82 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief parallelisation wrapper for "omp_set_tsal" +!> @param[in] ismpl local sample index + SUBROUTINE set_tsal(ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_set_tsal(ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate total salinity +!> @param[in] ismpl local sample index +!> @details +!>calculate total salinity\n + SUBROUTINE omp_set_tsal(ismpl) + use arrays + use mod_conc + use mod_genrl + use mod_genrlc + use mod_linfos + IMPLICIT NONE + + integer :: ismpl + integer :: i, j, k + INTEGER species + DOUBLE PRECISION summ, fac + +!$OMP master + IF (linfos(3)>=2) WRITE(*,'(1A)') & + ' ... setting total salinity' +!$OMP end master + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + summ = 0.D0 + DO species = 1, ntrans + fac = mmas_c(species)/mmas_nacl + summ = summ + fac*conc(i,j,k,species,ismpl) + END DO + tsal(i,j,k,ismpl) = summ + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END diff --git a/forward/set_var_deltat.f90 b/forward/set_var_deltat.f90 new file mode 100644 index 0000000..d35d467 --- /dev/null +++ b/forward/set_var_deltat.f90 @@ -0,0 +1,83 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief Set variable time step size variables delt_count and flag_delt +!> @param[in] iter_nl nonlinear iteration counter +!> @param[in] ismpl local sample index +!> @details +!> Set variable time step size variables delt_count and flag_delt +subroutine set_var_deltat(iter_nl, ismpl) + + use arrays, only: delt_count, flag_delt + use mod_genrl, only: iter_nlold, maxiter_nl, delt_double, nlconverge + use mod_linfos, only: linfos + + implicit none + + ! local sample index + integer :: ismpl + + ! nonlinear iteration counter + integer, intent (in) :: iter_nl + + ! Set delt_count + ! ------------------ + + ! Test whether to hasten or prevent time-step doubling + IF (iter_nl+iter_nlold.LT.maxiter_nl/2) THEN + delt_count(ismpl) = MIN(delt_count(ismpl)+2,delt_double-1) + ELSE IF (iter_nl+iter_nlold.LT.maxiter_nl) THEN + delt_count(ismpl) = MIN(delt_count(ismpl)+1,delt_double-1) + ELSE IF (iter_nl+iter_nlold.GT.maxiter_nl) THEN + delt_count(ismpl) = MAX(delt_count(ismpl)-1,0) + END IF + + ! Standard output + IF (linfos(3)>=2) WRITE (*,*) 'delt_count', delt_count(ismpl), & + 'delt_double', delt_double, 'iter_nlold', iter_nlold + + ! Set counter for next iteration + iter_nlold = iter_nl/4 + (3*iter_nlold)/4 + + ! Set flag_delt + ! ------------------ + + ! Test if nonlinear iteration reached maximum iteration count + IF (((iter_nl.EQ.maxiter_nl).OR.(flag_delt(ismpl).EQ.(-1)))) THEN + + IF (iter_nl.EQ.maxiter_nl .AND. (nlconverge .eq. 0)) THEN + WRITE(*,*) "Nonlinear iteration reached maximum iteration ", iter_nl, ". Set flag_delt to -2." + END IF + + IF (flag_delt(ismpl).EQ.(-1)) THEN + WRITE(*,*) "Iterative Solver reached maximum iteration. Set flag_delt to -2." + END IF + + flag_delt(ismpl) = -2 + + ELSE IF (flag_delt(ismpl).EQ.0) THEN + + flag_delt(ismpl) = flag_delt(ismpl) + 1 + + END IF + +end subroutine set_var_deltat diff --git a/forward/shemach/compress_file.f90 b/forward/shemach/compress_file.f90 new file mode 100644 index 0000000..30e9aa6 --- /dev/null +++ b/forward/shemach/compress_file.f90 @@ -0,0 +1,45 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compress a file (to *.bz2, *.zip, *.gz) +!> @param[in] fname file to compress +!> @param[in] ctool index number of the compression tool + SUBROUTINE compress_file(ctool,fname) + use arrays + IMPLICIT NONE + character (len=*) :: fname + INTEGER ctool + INTRINSIC trim + +! no compression + IF (compress_suffix(ctool)=='plain') RETURN +! bzip2 + IF (compress_suffix(ctool)=='bz2') CALL system('bzip2 -f -9 "' & + //trim(fname)//'"') +! gnu zip + IF (compress_suffix(ctool)=='gz') CALL system('gzip -f -9 "'// & + trim(fname)//'"') +! std. zip + IF (compress_suffix(ctool)=='zip') CALL system('zip -m -9 "'// & + trim(fname)//'.zip" "'//trim(fname)//'"') + RETURN + END diff --git a/forward/shemach/sys_cputime.f90 b/forward/shemach/sys_cputime.f90 new file mode 100644 index 0000000..ba35e51 --- /dev/null +++ b/forward/shemach/sys_cputime.f90 @@ -0,0 +1,39 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief function wrapper for the current time +!> @param[out] tsec current time + SUBROUTINE sys_cputime(tsec) + IMPLICIT NONE + DOUBLE PRECISION tsec +#ifndef fOMP + REAL (kind=4) :: ticks +#endif + DOUBLE PRECISION, EXTERNAL :: omp_get_wtime +#ifdef fOMP + tsec = omp_get_wtime() +#else + CALL cpu_time(ticks) + tsec = ticks +#endif + RETURN + END diff --git a/forward/shemach/sys_mkdir.f90 b/forward/shemach/sys_mkdir.f90 new file mode 100644 index 0000000..373659c --- /dev/null +++ b/forward/shemach/sys_mkdir.f90 @@ -0,0 +1,40 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief creates a directory +!> @param[in] string directory name + SUBROUTINE sys_mkdir(string) + IMPLICIT NONE +!aw integer perm, erro + character (len=*) :: string + INTRINSIC trim + +!aw erro=0 +!aw call MKDIR(strng,perm,erro) + CALL system('mkdir '//trim(string)) +!aw if (erro.ne.0) then +!aw write(*,'(a,i4,a,a,a,i3)') +!aw & 'error ',erro,' opening file: ',string +!aw *,' permissions: ',perm +!aw endif + RETURN + END diff --git a/forward/stab_param.f90 b/forward/stab_param.f90 new file mode 100644 index 0000000..1e55165 --- /dev/null +++ b/forward/stab_param.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief stabilise paramter (cutting to its limits) +!> @param[in] value paramter value +!> @param[in] s_k component index (parameter type) +!> @param[in] s_u unit index + SUBROUTINE stab_param(value,s_k,s_u) + use arrays + IMPLICIT NONE + DOUBLE PRECISION value + INTEGER s_k, s_u +! + IF (s_k>nprop_load) THEN + WRITE(*,'(1A,2I4,1A)') 'error: component index out of range (component,unit)=', s_k, s_u, '!' + STOP + END IF + IF (s_u>nunits) THEN + WRITE(*,'(1A,2I4,1A)') 'error: unit index out of range (component,unit)=', s_k, s_u, '!' + STOP + END IF + IF (value>prop_max(s_k)) THEN + WRITE(*,'(3A,1I4.4,1A,2(1e16.8,1A))') 'warning: cut ',properties(s_k),'_unit',s_u,' =',value,' to ',prop_max(s_k),' !' + value = prop_max(s_k) + END IF + IF (value<prop_min(s_k)) THEN + WRITE(*,'(3A,1I4.4,1A,2(1e16.8,1A))') 'warning: cut ',properties(s_k),'_unit',s_u,' =',value,' to ',prop_min(s_k),' !' + value = prop_min(s_k) + END IF + RETURN + END diff --git a/forward/static_relaxation.f90 b/forward/static_relaxation.f90 new file mode 100644 index 0000000..50e33ff --- /dev/null +++ b/forward/static_relaxation.f90 @@ -0,0 +1,70 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief Compute static relaxation for flow and temperature +!> @param[in] ijk number of cells +!> @param[inout] ismpl local sample index +!> @details +!> Static relaxation is computed for variable arrays head, pres, temp: +!> \n\n +!> +!> var = (1-theta)*varold + theta*var \n +subroutine static_relaxation(ijk,ismpl) + + use arrays, only: head, headold, pres, presold, temp, tempold + use mod_genrl, only: cgen_time + use mod_time, only: thetaf, thetat + + implicit none + + ! local sample index + integer :: ismpl + + ! Number of cells + integer, intent (in) :: ijk + + + ! flow + if (thetaf /= 1.0d0) then + +#ifdef head_base + CALL dscal(ijk,thetaf,head(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-thetaf,headold(1,cgen_time,ismpl),1,head(1,1,1,ismpl),1) +#endif +#ifdef pres_base + CALL dscal(ijk,thetaf,pres(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-thetaf,presold(1,cgen_time,ismpl),1,pres(1,1,1,ismpl),1) +#endif + + end if + + ! temperature + if (thetat /= 1.0d0) then + + CALL dscal(ijk,thetat,temp(1,1,1,ismpl),1) + CALL daxpy(ijk,1.0D0-thetat,tempold(1,cgen_time,ismpl),1,temp(1,1,1,ismpl),1) + + end if + + return + +end subroutine static_relaxation diff --git a/forward/strngut/beginlast.f90 b/forward/strngut/beginlast.f90 new file mode 100644 index 0000000..dc72d6a --- /dev/null +++ b/forward/strngut/beginlast.f90 @@ -0,0 +1,45 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the position of the first non-separator character of the last non-seperator block +!> @param[in] string search string +!> @return position of the first non-separator character +!> @details +!> returns the position of the first non-separator character of the \n +!> last non-seperator block\n + INTEGER FUNCTION beginlast(string) + IMPLICIT NONE + character (len=*) :: string + INTEGER i + INTRINSIC achar + + beginlast = 1 + DO i = len(string), 1, -1 + IF (string(i:i)==' ' .OR. string(i:i)==',' .OR. & + string(i:i)==';' .OR. string(i:i)==':' .OR. & + string(i:i)=='=' .OR. string(i:i)==achar(9)) THEN + beginlast = i + RETURN + END IF + END DO + RETURN + END diff --git a/forward/strngut/cfirst.f90 b/forward/strngut/cfirst.f90 new file mode 100644 index 0000000..e2039a6 --- /dev/null +++ b/forward/strngut/cfirst.f90 @@ -0,0 +1,42 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the position of the first non-separator character in string +!> @param[in] string search string +!> @return position of the first non-separator character +!> @details +!> (a modified copy of "lblank")\n + INTEGER FUNCTION cfirst(string) + IMPLICIT NONE + character (len=*) :: string + INTRINSIC achar + + DO cfirst = 1, len(string) + IF (string(cfirst:cfirst)/=' ' .AND. & + string(cfirst:cfirst)/=',' .AND. string(cfirst:cfirst)/= & + ';' .AND. string(cfirst:cfirst)/=':' .AND. & + string(cfirst:cfirst)/='=' .AND. string(cfirst:cfirst)/= & + achar(9)) RETURN + END DO + cfirst = len(string) + 1 + RETURN + END diff --git a/forward/strngut/chln.f90 b/forward/strngut/chln.f90 new file mode 100644 index 0000000..b0d5973 --- /dev/null +++ b/forward/strngut/chln.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns positions of first and last non-blank character +!> @param[in] text string line +!> @param[out] ianf first non-blank character +!> @param[out] iend last non-blank character +!> @details +!> returns positions of first and last non-blank character in string\n + SUBROUTINE chln(text,ianf,iend) + IMPLICIT NONE + INTEGER i, j, l, ianf, iend + character (len=*) :: text + LOGICAL lead, trail + + lead = .TRUE. + trail = .TRUE. + l = len(text) +! + DO i = 1, l + IF (lead .AND. text(i:i)/=' ') THEN +! first non-blank CharaCter: store ianf + ianf = i + lead = .FALSE. + END IF +! + j = l - i + 1 + IF (trail .AND. text(j:j)/=' ') THEN +! last non-blank CharaCter: store iend + iend = j + trail = .FALSE. + END IF + IF (( .NOT. lead) .AND. ( .NOT. trail)) RETURN + END DO +! +! error return, all string blank + ianf = 0 + iend = 0 +! + RETURN + END diff --git a/forward/strngut/clast.f90 b/forward/strngut/clast.f90 new file mode 100644 index 0000000..cfa7448 --- /dev/null +++ b/forward/strngut/clast.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the position of the last non-separator character in string +!> @param[in] string search string +!> @return position of the last non-separator character +!> @details +!> (a modified copy of "lblank")\n + INTEGER FUNCTION clast(string) + IMPLICIT NONE + character (len=*) :: string + INTRINSIC achar + + DO clast = len(string), 1, -1 + IF (string(clast:clast)/=' ' .AND. string(clast:clast)/=',' & + .AND. string(clast:clast)/=';' .AND. & + string(clast:clast)/=':' .AND. string(clast:clast)/='=' & + .AND. string(clast:clast)/=achar(9)) RETURN + END DO + clast = 0 + RETURN + END diff --git a/forward/strngut/found.f90 b/forward/strngut/found.f90 new file mode 100644 index 0000000..378c289 --- /dev/null +++ b/forward/strngut/found.f90 @@ -0,0 +1,74 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief locate keyword in file 'ifil', begin at position 1 +!> @param[in] ifil file handler of the opened file +!> @param[in] key section name +!> @param[out] block_s current/last readed line from file +!> @param[in] need_it "true": stop when not found (generate an error for important sections) +!> @return "true" when section (key) found in file + LOGICAL FUNCTION found(ifil,key,block_s,need_it) + USE mod_genrl + IMPLICIT NONE + INTEGER ifil, iwrd, kb, ke + character (len=*) :: key, block_s + LOGICAL need_it + + INTEGER lblank, locstr + EXTERNAL lblank, locstr + + iwrd = 1 + found = .FALSE. + +! search dataset + CALL chln(key,kb,ke) + +10 CONTINUE + READ(ifil,'(a)',end=15,err=15) block_s + found = locstr(block_s,key(kb:ke)) == 1 +! no matching, try next (10) + IF ( .NOT. found .OR. lblank(block_s)==0 .OR. & + block_s(1:1)/=key_char) GO TO 10 + RETURN + +! end of file -> reading file again +15 CONTINUE + REWIND ifil + +20 CONTINUE + READ(ifil,'(a)',end=25,err=25) block_s + found = locstr(block_s,key(kb:ke)) == 1 +! no matching, try next (20) + IF ( .NOT. found .OR. lblank(block_s)==0 .OR. & + block_s(1:1)/=key_char) GO TO 20 + RETURN + +! end of file -> array not in file +25 REWIND ifil + IF (need_it) THEN + WRITE(*,*) 'error: reading field "', key(kb:ke), & + '", not found!' + STOP + END IF + + RETURN + END diff --git a/forward/strngut/get_arg.f90 b/forward/strngut/get_arg.f90 new file mode 100644 index 0000000..ddccf71 --- /dev/null +++ b/forward/strngut/get_arg.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the begin and the end of the argument of the key in the line string +!> @param[in] key search string +!> @param[in] line current character line (find here the key) +!> @param[out] first begin index of the argument +!> @param[out] last end index of the argument + SUBROUTINE get_arg(key,line,first,last) + IMPLICIT NONE + character (len=*) :: key, line + INTEGER first, last, locstr, cfirst + EXTERNAL locstr, cfirst + INTRINSIC achar + + last = 0 + first = locstr(line,key) + IF (first==0) RETURN +! + first = first + len(key) + first = first - 1 + cfirst(line(first:len(line))) +! + DO last = first, len(line) - 1 + IF (line(last+1:last+1)==' ' .OR. line(last+1:last+1)==',' & + .OR. line(last+1:last+1)==';' .OR. & + line(last+1:last+1)==':' .OR. line(last+1:last+1)=='=' & + .OR. line(last+1:last+1)==achar(9)) RETURN + END DO + last = len(line) +! + RETURN + END diff --git a/forward/strngut/lblank.f90 b/forward/strngut/lblank.f90 new file mode 100644 index 0000000..96e0056 --- /dev/null +++ b/forward/strngut/lblank.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the position of the last non-blank character in string +!> @param[in] string search string +!> @return position of the last non-blank character +!> @details +!> (actually there is a standard unix function of the same name\n +!> that does the exactly same thing. this is provided for\n +!> compatibility on non-unix systems.)\n + INTEGER FUNCTION lblank(string) + IMPLICIT NONE + character (len=*) :: string + INTRINSIC achar + + DO lblank = len(string), 1, -1 + IF (string(lblank:lblank)/=' ' .AND. & + string(lblank:lblank)/=achar(9)) RETURN + END DO + lblank = 0 + RETURN + END diff --git a/forward/strngut/locstr.f90 b/forward/strngut/locstr.f90 new file mode 100644 index 0000000..35a49b6 --- /dev/null +++ b/forward/strngut/locstr.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns the position of str2 in str1 ignores case +!> @param[in] str1 string where to find str2 +!> @param[in] str2 search string (key) +!> @return position of str2 in str1 +!> @details +!> returns 0 if str2 not found in str1\n + INTEGER FUNCTION locstr(str1,str2) + IMPLICIT NONE + character (len=*) :: str1, str2 + INTEGER i, j, capdif + LOGICAL same + + locstr = 0 + capdif = ichar('a') - ichar('A') +! + DO i = 1, len(str1) - len(str2) + 1 + same = .TRUE. + DO j = 1, len(str2) + same = same .AND. (str1(i+j-1:i+j-1)==str2(j:j) .OR. 'A'<= & + str2(j:j) .AND. str2(j:j)<='Z' .AND. ichar(str1(i+j-1:i+ & + j-1))==ichar(str2(j:j))+capdif .OR. 'a'<=str2(j:j) .AND. & + str2(j:j)<='z' .AND. ichar(str1(i+j-1:i+ & + j-1))==ichar(str2(j:j))-capdif) + END DO + IF (same) THEN + locstr = i + RETURN + END IF + END DO +! + RETURN + END diff --git a/forward/strngut/sfirst.f90 b/forward/strngut/sfirst.f90 new file mode 100644 index 0000000..a379b4e --- /dev/null +++ b/forward/strngut/sfirst.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns position before the first separator character in string (special version) +!> @param[in] string search string +!> @return position before the first separator character +!> @details +!> special version for reading extended parameters (used in "no_ext_link")\n + INTEGER FUNCTION sfirst(string) + IMPLICIT NONE + character (len=*) :: string + INTEGER i + INTRINSIC achar + + sfirst = 0 + DO i = 1, len(string) + IF (string(i:i)==',' .OR. string(i:i)==';' .OR. & + string(i:i)==':' .OR. string(i:i)=='=') RETURN + IF (string(i:i)/=' ' .AND. string(i:i)/=achar(9)) sfirst = i + END DO + RETURN + END diff --git a/forward/temp/calc_temp.f90 b/forward/temp/calc_temp.f90 new file mode 100644 index 0000000..df1cfb5 --- /dev/null +++ b/forward/temp/calc_temp.f90 @@ -0,0 +1,90 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief top level routine for setup and compute temperature +!> @param[in] ismpl local sample index + SUBROUTINE calc_temp(ismpl) + use arrays + use mod_genrlc + use mod_genrl + use mod_temp + use mod_time + use mod_linfos + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION vxc, vyc, vzc, por, kx, ky, kz, lx, ly, lz, & + rhoceff + EXTERNAL vxc, vyc, vzc, por, kx, ky, kz, lx, ly, lz, rhoceff + DOUBLE PRECISION vx, vy, vz, rhocf, rhocm + EXTERNAL vx, vy, vz, rhocf, rhocm + INTEGER ijk + integer :: i + integer :: ismpl + + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_temp' +! +! selecting a part for each thread +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + + ijk = i0*j0*k0 +! default to mark a non-boundary +!$OMP master + DO i = 1, ijk + bc_mask(i,ismpl) = '+' + END DO +!$OMP end master +! initialize coefficients for sparse solvers + CALL omp_set_dval(ijk,0.D0,a(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,b(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,c(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,d(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,e(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,f(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,g(1,1,1,ismpl)) + CALL omp_set_dval(ijk,0.D0,w(1,1,1,ismpl)) + +!$OMP barrier +! calculate coefficients + CALL set_tcoef(ismpl) +! set energy sources/sinks + CALL set_tq(ismpl) + +!$OMP barrier + CALL set_tcoefrs(ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + +! set boundary conditions + CALL set_tbc(ismpl) + + IF (linfos(3)>=2) WRITE(*,*) ' ... solve(temp)' +! solve it + CALL solve(pv_temp,-1,temp(1,1,1,ismpl),errt,apart,controlt, & + ismpl) + + RETURN + END diff --git a/forward/temp/neumann_temp.f90 b/forward/temp/neumann_temp.f90 new file mode 100644 index 0000000..cdea387 --- /dev/null +++ b/forward/temp/neumann_temp.f90 @@ -0,0 +1,203 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_neumann_temp" +!> @param[out] neumann_max neumann criteria +!> @param[in] ismpl local sample index + SUBROUTINE neumann_temp(neumann_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION neumann_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_neumann_temp(neumann_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif + + RETURN + END + +!> @brief calculate grid neuman numbers (temp) +!> @param[out] neumann_max maximal neuman number +!> @param[in] ismpl local sample index + SUBROUTINE omp_neumann_temp(neumann_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + INTEGER c1, c2, c3 + DOUBLE PRECISION neumann_maxx, neumann_minx, neumann_avgx + DOUBLE PRECISION neumann_maxy, neumann_miny, neumann_avgy + DOUBLE PRECISION neumann_maxz, neumann_minz, neumann_avgz + DOUBLE PRECISION val, neumann_max, delt, fac, davg + DOUBLE PRECISION deltat + EXTERNAL deltat + DOUBLE PRECISION li, lj, lk, rhocf, por, rhoceff + EXTERNAL li, lj, lk, rhocf, por, rhoceff + + + delt = deltat(simtime(ismpl),ismpl) + + IF ( .NOT. (transient .AND. tr_switch(ismpl))) THEN +!$OMP master + WRITE(*,*) ' neumann-temp: not defined for steady state' +!$OMP end master + RETURN + ELSE IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... neumann-temp: delt/tunit = ', & + delt/tunit + WRITE(*,*) +!$OMP end master + END IF + +! val in x + c1 = 0 + neumann_maxx = small + neumann_minx = big + neumann_avgx = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + fac = delt/rhoceff(i,j,k,ismpl) + val = fac*li(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxx) neumann_maxx = val + IF (val<neumann_minx) neumann_minx = val + neumann_avgx = neumann_avgx + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in y + c2 = 0 + neumann_maxy = small + neumann_miny = big + neumann_avgy = 0.0D0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + fac = delt/rhoceff(i,j,k,ismpl) + val = fac*lj(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxy) neumann_maxy = val + IF (val<neumann_miny) neumann_miny = val + neumann_avgy = neumann_avgy + val + END DO + END DO + END DO +!$OMP end do nowait + +! val in z + c3 = 0 + neumann_maxz = small + neumann_minz = big + neumann_avgz = 0.0D0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + fac = delt/rhoceff(i,j,k,ismpl) + val = fac*lk(i,j,k,ismpl)/(davg*davg) + IF (val>neumann_maxz) neumann_maxz = val + IF (val<neumann_minz) neumann_minz = val + neumann_avgz = neumann_avgz + val + END DO + END DO + END DO +!$OMP end do nowait + +! compute global sum for all values + CALL omp_summe(neumann_maxx,neumann_minx,neumann_avgx, & + neumann_maxy,neumann_miny,neumann_avgy,neumann_maxz, & + neumann_minz,neumann_avgz,c1,c2,c3,ismpl) + +!$OMP master + IF (i0>2) THEN + neumann_avgx = neumann_avgx/dble(c1) + ELSE + neumann_maxx = 0.0D0 + neumann_minx = 0.0D0 + neumann_avgx = 0.0D0 + END IF + IF (j0>2) THEN + neumann_avgy = neumann_avgy/dble(c2) + ELSE + neumann_maxy = 0.0D0 + neumann_miny = 0.0D0 + neumann_avgy = 0.0D0 + END IF + IF (k0>2) THEN + neumann_avgz = neumann_avgz/dble(c3) + ELSE + neumann_maxz = 0.0D0 + neumann_minz = 0.0D0 + neumann_avgz = 0.0D0 + END IF + + neumann_max = max(neumann_maxx,neumann_maxy,neumann_maxz) + + IF (linfos(3)>=2) THEN + WRITE(*,*) 'neumann number for temperature in x,y,z:' + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' max. : ', & + neumann_maxx, ', ', neumann_maxy, ', ', neumann_maxz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' min. : ', & + neumann_minx, ', ', neumann_miny, ', ', neumann_minz + WRITE(*,'(a,1e10.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + neumann_avgx, ', ', neumann_avgy, ', ', neumann_avgz + END IF + + IF (linfos(3)>=1 .AND. neumann_max>1.D0) THEN + WRITE(*,'(a)') & + '!!!: neumann temp number(s) greater than 1 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', & + neumann_maxx, 'y: ', neumann_maxy, 'z: ', neumann_maxz + WRITE(*,*) + END IF +!$OMP end master + + RETURN + END diff --git a/forward/temp/peclet_temp.f90 b/forward/temp/peclet_temp.f90 new file mode 100644 index 0000000..70fa6e4 --- /dev/null +++ b/forward/temp/peclet_temp.f90 @@ -0,0 +1,217 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_peclet_temp" +!> @param[out] peclet_max peclet criteria +!> @param[in] ismpl local sample index + SUBROUTINE peclet_temp(peclet_max,ismpl) + use mod_genrl + use mod_OMP_TOOLS + IMPLICIT NONE + integer :: ismpl + INCLUDE 'OMP_TOOLS.inc' + DOUBLE PRECISION peclet_max + +#ifdef fOMP +!$OMP parallel num_threads(Tlevel_1) +!$ call omp_binding(ismpl) +#endif + CALL omp_peclet_temp(peclet_max,ismpl) +#ifdef fOMP +!$OMP end parallel +#endif +! + RETURN + END + +!> @brief calculate grid peclet numbers (temperature) +!> @param[out] peclet_max peclet criteria +!> @param[in] ismpl local sample index + SUBROUTINE omp_peclet_temp(peclet_max,ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + INTEGER c1, c2, c3 + DOUBLE PRECISION peclet_maxx, peclet_minx, peclet_avgx, & + peclet_maxy, peclet_miny, peclet_avgy, peclet_maxz, & + peclet_minz, peclet_avgz, val, davg, peclet_max + INTEGER ipt, jpt, kpt + DOUBLE PRECISION li, lj, lk, rhocf, vx, vy, vz, por + EXTERNAL li, lj, lk, rhocf, vx, vy, vz, por + + IF (linfos(3)>=2) THEN +!$OMP master + WRITE(*,*) + WRITE(*,'(A,1e16.8)') ' ... peclet-temp' + WRITE(*,*) +!$OMP end master + END IF +! +! temperature-val in x + peclet_maxx = small + peclet_minx = big + peclet_avgx = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c1 = 0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 1, j0 + DO i = 2, i0 - 1 + c1 = c1 + 1 + davg = 0.5D0*(delx(i)+delx(i+1)) + val = abs(vx(i,j,k,ismpl))*davg/li(i,j,k,ismpl) + IF (val>peclet_maxx) THEN + peclet_maxx = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_minx) peclet_minx = val + peclet_avgx = peclet_avgx + val + END DO + END DO + END DO +!$OMP end do nowait +! if (linfos(3).ge.2)write(*,*) +! & "max. temp-val in x: ", ipt,jpt,kpt +! +! temperature-val in y + peclet_maxy = small + peclet_miny = big + peclet_avgy = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c2 = 0 +!$OMP do schedule(static) + DO k = 1, k0 + DO j = 2, j0 - 1 + DO i = 1, i0 + c2 = c2 + 1 + davg = 0.5D0*(dely(j)+dely(j+1)) + val = abs(vy(i,j,k,ismpl))*davg/lj(i,j,k,ismpl) + IF (val>peclet_maxy) THEN + peclet_maxy = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_miny) peclet_miny = val + peclet_avgy = peclet_avgy + val + END DO + END DO + END DO +!$OMP end do nowait +! if(linfos(3).ge.2) +! & write(*,*)"max. temp-val in y: " ,ipt,jpt,kpt +! +! temperature-val in z + peclet_maxz = small + peclet_minz = big + peclet_avgz = 0.0D0 + val = 0.0D0 + ipt = 0 + jpt = 0 + kpt = 0 + c3 = 0 +!$OMP do schedule(static) + DO k = 2, k0 - 1 + DO j = 1, j0 + DO i = 1, i0 + c3 = c3 + 1 + davg = 0.5D0*(delz(k)+delz(k+1)) + val = abs(vz(i,j,k,ismpl))*davg/lk(i,j,k,ismpl) + IF (val>peclet_maxz) THEN + peclet_maxz = val + ipt = i + jpt = j + kpt = k + END IF + IF (val<peclet_minz) peclet_minz = val + peclet_avgz = peclet_avgz + val + END DO + END DO + END DO +!$OMP end do nowait +! if(linfos(3).ge.2) +! & write(*,*)"max. temp-val in z: " ,ipt,jpt,kpt +! +! compute global sum for all values + CALL omp_summe(peclet_maxx,peclet_minx,peclet_avgx, & + peclet_maxy,peclet_miny,peclet_avgy,peclet_maxz,peclet_minz, & + peclet_avgz,c1,c2,c3,ismpl) +! +!$OMP master + IF (i0>2) THEN + peclet_avgx = peclet_avgx/dble(c1) + ELSE + peclet_maxx = 0.0D0 + peclet_minx = 0.0D0 + peclet_avgx = 0.0D0 + END IF + IF (j0>2) THEN + peclet_avgy = peclet_avgy/dble(c2) + ELSE + peclet_maxy = 0.0D0 + peclet_miny = 0.0D0 + peclet_avgy = 0.0D0 + END IF + IF (k0>2) THEN + peclet_avgz = peclet_avgz/dble(c3) + ELSE + peclet_maxz = 0.0D0 + peclet_minz = 0.0D0 + peclet_avgz = 0.0D0 + END IF +! + peclet_max = max(peclet_avgx,peclet_avgy,peclet_avgz) +! + IF (linfos(3)>=2) THEN + WRITE(*,*) 'peclet number for temperature in x,y,z:' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' max. : ', & + peclet_maxx, ', ', peclet_maxy, ', ', peclet_maxz + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' min. : ', & + peclet_minx, ', ', peclet_miny, ', ', peclet_minz + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') ' avg. : ', & + peclet_avgx, ', ', peclet_avgy, ', ', peclet_avgz + END IF +! + IF (peclet_max>2.0D0 .AND. linfos(3)>=1) THEN + WRITE(*,'(1A)') '!!!: peclet number for temperature > 2 :' + WRITE(*,'(a,1e12.3,a,1e10.3,a,1e10.3)') 'x: ', peclet_maxx, & + 'y: ', peclet_maxy, 'z: ', peclet_maxz + END IF +!$OMP end master +! + RETURN + END diff --git a/forward/temp/set_tbc.f90 b/forward/temp/set_tbc.f90 new file mode 100644 index 0000000..1a25ab2 --- /dev/null +++ b/forward/temp/set_tbc.f90 @@ -0,0 +1,286 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief coefficents for the heat equation +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the heat equation according to the prescribed sources and sinks.\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_tbc(ismpl) + use arrays + use mod_genrl + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu + ! INTEGER ac, bc + INTEGER tpbcu, bctype, i_dir + DOUBLE PRECISION val, malfa, mbeta, vx, vy, vz, dv, ds, vv + EXTERNAL vx, vy, vz + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! flow due to flow neumann nodes / wellars - - - - - - - - - - - - - - + + DO ib = first_flow, last_flow + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "neumann"?, skip otherwise + IF (bctype==bt_neum.OR.bctype==bt_neuw) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_hbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + +! wellar test + IF (val<0.0D0 .AND. tpbcu>=0) THEN + ds = 0.D0 + dv = 0.D0 + IF (i>1) THEN + vv = abs(vx(i-1,j,k,ismpl)) + ds = ds + vv + dv = dv + temp(i-1,j,k,ismpl)*vv +! write(*,*) 'i- ',vv, temp(i-1,j,k,ismpl) + END IF + IF (i<i0) THEN + vv = abs(vx(i,j,k,ismpl)) + ds = ds + vv + dv = dv + temp(i+1,j,k,ismpl)*vv +! write(*,*) 'i+ ',vv, temp(i+1,j,k,ismpl) + END IF + IF (j>1) THEN + vv = abs(vy(i,j-1,k,ismpl)) + ds = ds + vv + dv = dv + temp(i,j-1,k,ismpl)*vv +! write(*,*) 'j- ',vv, temp(i,j-1,k,ismpl) + END IF + IF (j<j0) THEN + vv = abs(vy(i,j,k,ismpl)) + ds = ds + vv + dv = dv + temp(i,j+1,k,ismpl)*vv +! write(*,*) 'j+ ',vv, temp(i,j+1,k,ismpl) + END IF + IF (k>1) THEN + vv = abs(vz(i,j,k-1,ismpl)) + ds = ds + vv + dv = dv + temp(i,j,k-1,ismpl)*vv +! write(*,*) 'k- ',vv, temp(i,j,k-1,ismpl) + END IF + IF (k<k0) THEN + vv = abs(vz(i,j,k,ismpl)) + ds = ds + vv + dv = dv + temp(i,j,k+1,ismpl)*vv +! write(*,*) 'k+ ',vv, temp(i-1,j,k+1,ismpl) + END IF + dv = dv/ds +! write(*,*) 'val: ',dv,ds +! apply dirichlet update [dv] +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*dv +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = dv + temp(i,j,k,ismpl) = dv +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_temp, last_temp + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_tbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN +#ifdef BCMY +! D = D+my + d(i,j,k,ismpl) = d(i,j,k,ismpl) - dbc_data(ib,2,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + dbc_data(ib,2,ismpl)*val +#else +! standard boundary condition handling + a(i,j,k,ismpl) = 0.0D0 + b(i,j,k,ismpl) = 0.0D0 + c(i,j,k,ismpl) = 0.0D0 + e(i,j,k,ismpl) = 0.0D0 + f(i,j,k,ismpl) = 0.0D0 + g(i,j,k,ismpl) = 0.0D0 + d(i,j,k,ismpl) = 1.0D0 + w(i,j,k,ismpl) = val + temp(i,j,k,ismpl) = val +! mark as boundary for normalising the lin. system + bc_mask(i+(j-1)*i0+(k-1)*i0*j0,ismpl) = '0' +#endif + END IF + END IF + END DO + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! neumann nodes - - - - - - - - - - - - - - - - - - - - - - - - - - + + DO ib = first_temp, last_temp + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) + i_dir = ibc_data(ib,cbc_dir) +! "neumann"?, skip otherwise + IF (bctype==bt_neum) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_tbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) THEN + IF ((i_dir==0)) val = val/(delx(i)*dely(j)*delz(k)) + IF ((i_dir==1) .OR. (i_dir==2)) val = val/delx(i) + IF ((i_dir==3) .OR. (i_dir==4)) val = val/dely(j) + IF ((i_dir==5) .OR. (i_dir==6)) val = val/delz(k) + + w(i,j,k,ismpl) = w(i,j,k,ismpl) - val + END IF + END IF + END DO + + RETURN + END + +!> @brief modify TEMP for the heat equation according +!> @param[in] ismpl local sample index +!> @details +!> modify TEMP for the heat equation according to the boundary conditions.\n + SUBROUTINE set_dtbc(ismpl) + use arrays + use mod_genrl + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + integer :: ib + INTEGER bcu, tpbcu, bctype + DOUBLE PRECISION val, malfa, mbeta + INTRINSIC max + + +! - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +! dirichlet nodes - - - - - - - - - - - - - - - - - - - - - - - - - - - + +!$OMP do schedule(static) + DO ib = first_temp, last_temp + i = ibc_data(ib,cbc_i) + j = ibc_data(ib,cbc_j) + k = ibc_data(ib,cbc_k) + bcu = ibc_data(ib,cbc_bcu) + tpbcu = max(ibc_data(ib,cbc_bctp),0) + bctype = ibc_data(ib,cbc_bt) +! "dirichlet"?, skip otherwise + IF (bctype==bt_diri) THEN +! discrete values + IF (bcu<=0) THEN + val = dbc_data(ib,1,ismpl) + ELSE + val = propunit(bcu,idx_tbc,ismpl) + END IF + + IF ((tpbcu>0) .AND. nbctp>0) THEN +! time-dependent bc: val=ac*val+bc +! get Alfa and Beta modificators + CALL get_tpbcalbe(malfa,mbeta,tpbcu,ismpl) +! update time dependend modification of the bc-value + val = malfa + mbeta*val + END IF + + IF (tpbcu>=0) temp(i,j,k,ismpl) = val + END IF + END DO +!$OMP end do nowait + + RETURN + END diff --git a/forward/temp/set_tcoef.f90 b/forward/temp/set_tcoef.f90 new file mode 100644 index 0000000..bac48fb --- /dev/null +++ b/forward/temp/set_tcoef.f90 @@ -0,0 +1,274 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate coefficents for the heat equation +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the heat equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_tcoef(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + DOUBLE PRECISION li, lj, lk, rhocf, vx, vy, vz, alfa, amean + EXTERNAL li, lj, lk, rhocf, vx, vy, vz, alfa, amean + + DOUBLE PRECISION rijk, ra, rc, va, la, alf, p2 + + +!$OMP master + IF (linfos(3)>=2) WRITE(*,*) ' ... tcoef' +!$OMP end master + +! initialize coefficients for sparse solvers + +! inner points of grid - - - - - - - - - - - - - - - - - - - - - - - - - + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + + rijk = rhocf(i,j,k,ismpl) + + IF (i0>1) THEN + IF (i<i0) THEN + la = li(i,j,k,ismpl) + ra = amean(rhocf(i+1,j,k,ismpl),rijk) + va = vx(i,j,k,ismpl) + rc = 0.5*ra*va + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + alf = 0.D0 + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + e(i,j,k,ismpl) = (la-(1.D0-alf)*rc)/delx(i) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la+(1.D0+alf)*rc)/delx(i) + END IF + + IF (i>1) THEN + la = li(i-1,j,k,ismpl) + ra = amean(rhocf(i-1,j,k,ismpl),rijk) + va = vx(i-1,j,k,ismpl) + rc = 0.5*ra*va + alf = 0.D0 + IF (va==0.D0) THEN + alf = 0.D0 + ELSE + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + END IF + c(i,j,k,ismpl) = (la+(1.D0+alf)*rc)/delx(i) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la-(1.D0-alf)*rc)/delx(i) + END IF + END IF + + IF (j0>1) THEN + + IF (j<j0) THEN + la = lj(i,j,k,ismpl) + ra = amean(rhocf(i,j+1,k,ismpl),rijk) + va = vy(i,j,k,ismpl) + rc = 0.5D0*ra*va + alf = 0.D0 + IF (va==0.D0) THEN + alf = 0.D0 + ELSE + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + END IF + f(i,j,k,ismpl) = (la-(1.D0-alf)*rc)/dely(j) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la+(1.D0+alf)*rc)/dely(j) + END IF + + IF (j>1) THEN + la = lj(i,j-1,k,ismpl) + ra = amean(rhocf(i,j-1,k,ismpl),rijk) + va = vy(i,j-1,k,ismpl) + rc = 0.5*ra*va + alf = 0.D0 + IF (va==0.D0) THEN + alf = 0.D0 + ELSE + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + END IF + b(i,j,k,ismpl) = (la+(1.D0+alf)*rc)/dely(j) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la-(1.D0-alf)*rc)/dely(j) + END IF + END IF + + IF (k0>1) THEN + + IF (k<k0) THEN + la = lk(i,j,k,ismpl) + ra = amean(rhocf(i,j,k+1,ismpl),rijk) + va = vz(i,j,k,ismpl) + rc = 0.5*ra*va + alf = 0.D0 + IF (va==0.D0) THEN + alf = 0.D0 + ELSE + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + END IF + g(i,j,k,ismpl) = (la-(1.D0-alf)*rc)/delz(k) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la+(1.D0+alf)*rc)/delz(k) + END IF + + IF (k>1) THEN + la = lk(i,j,k-1,ismpl) + ra = amean(rhocf(i,j,k-1,ismpl),rijk) + va = vz(i,j,k-1,ismpl) + rc = 0.5*ra*va + alf = 0.D0 + IF (va==0.D0) THEN + alf = 0.D0 + ELSE + IF (la>0.D0) THEN + p2 = rc/la + alf = alfa(p2) + ELSE + IF (va<0.D0) alf = -1.D0 + IF (va>0.D0) alf = 1.D0 + END IF + END IF + a(i,j,k,ismpl) = (la+(1.D0+alf)*rc)/delz(k) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - & + (la-(1.D0-alf)*rc)/delz(k) + END IF + END IF + + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END + +!> @brief coefficents for the heat equation (here right hand side) +!> @param[in] ismpl local sample index +!> @details +!> calculate coefficents for the heat equation\n +!> coefficients are stored as vectors in the diagonals a-g (d center) and rhs in w.\n + SUBROUTINE set_tcoefrs(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_temp + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + + DOUBLE PRECISION deltt, rce + ! INTEGER c1, c2, c3, c4 + + DOUBLE PRECISION rhoceff, por, qt, deltat + EXTERNAL rhoceff, por, qt, deltat + + + deltt = deltat(simtime(ismpl),ismpl) + +! - - rhs: sources, also terms for transient caolculations - - - - - - - - - + + IF (transient .AND. tr_switch(ismpl)) THEN +! - - - - - - - transient - - - - - - - - - - - - - - - - - - - - - - - - - - + + CALL omp_mvp(i0,j0,k0,tempold(1,cgen_time,ismpl), & + x(1,1,1,ismpl),a(1,1,1,ismpl),b(1,1,1,ismpl), & + c(1,1,1,ismpl),d(1,1,1,ismpl),e(1,1,1,ismpl), & + f(1,1,1,ismpl),g(1,1,1,ismpl)) + +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 +! add solid and fluid heat production, boundary terms + rce = rhoceff(i,j,k,ismpl) + d(i,j,k,ismpl) = d(i,j,k,ismpl) - rce/(deltt*thetat) + w(i,j,k,ismpl) = w(i,j,k,ismpl) - & + rce*tempold(i+(j-1)*i0+(k-1)*i0*j0,cgen_time,ismpl)/ & + deltt - (1.D0-thetat)*x(i,j,k,ismpl) - & + hpf*por(i,j,k,ismpl) + w(i,j,k,ismpl) = w(i,j,k,ismpl)/thetat + END DO + END DO + END DO +!$OMP end do nowait + ELSE +! - - - - - - - - steady state - - - - - - - - - - - - - - - - - - - - - +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 +! solid and fluid heat production + w(i,j,k,ismpl) = w(i,j,k,ismpl) - hpf*por(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + END IF + + RETURN + END diff --git a/forward/temp/set_tq.f90 b/forward/temp/set_tq.f90 new file mode 100644 index 0000000..2974334 --- /dev/null +++ b/forward/temp/set_tq.f90 @@ -0,0 +1,76 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief modify coefficents for the temperature equation +!> @param[in] ismpl local sample index +!> @details +!> modify coefficents for the temperature equation according to the prescribed sources and sinks\n +!> rhs stored in w.\n + SUBROUTINE set_tq(ismpl) + use arrays + use mod_genrl + use mod_time + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION deltat, deltt, qt + EXTERNAL deltat, qt +! rhs: sources + IF (transient .AND. tr_switch(ismpl)) THEN + deltt = deltat(simtime(ismpl),ismpl) +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qt(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + ELSE +!$OMP do schedule(static) collapse(3) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + w(i,j,k,ismpl) = w(i,j,k,ismpl) - qt(i,j,k,ismpl) + END DO + END DO + END DO +!$OMP end do nowait + END IF + +! Heat sources associated with flow dirichlet nodes - - - - - - - + +! do ib=first_flow,last_flow +! i=ibc_data(ib,cbc_i) +! j=ibc_data(ib,cbc_j) +! k=ibc_data(ib,cbc_k) +! bctype=ibc_data(ib,cbc_bt) +! if (bctype.eq.bt_diri) then +! w(i,j,k)=w(i,j,k)-qheadbcd(i,j,k,ismpl) ??? Zeit-Abhaengikeit ??? +! write(99,'(3i6,4x,e15.5)') i,j,k,qheadbcd(i,j,k,ismpl) +! endif +! end do + + RETURN + END diff --git a/forward/temp/tfluxes.f90 b/forward/temp/tfluxes.f90 new file mode 100644 index 0000000..0d21998 --- /dev/null +++ b/forward/temp/tfluxes.f90 @@ -0,0 +1,356 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate x heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qx(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION dif, li + EXTERNAL li + + qx = 0.D0 + IF (i0>1 .AND. i<i0) THEN + dif = temp(i+1,j,k,ismpl) - temp(i,j,k,ismpl) + qx = -li(i,j,k,ismpl)*dif + END IF + RETURN + END + +!> @brief calculate y heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION dif, lj + EXTERNAL lj + + qy = 0.D0 + IF (j0>1 .AND. j<j0) THEN + dif = temp(i,j+1,k,ismpl) - temp(i,j,k,ismpl) + qy = -lj(i,j,k,ismpl)*dif + END IF + + RETURN + END + +!> @brief calculate z heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qz(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION dif, lk + EXTERNAL lk + + qz = 0.D0 + IF (k0>1 .AND. k<k0) THEN + dif = temp(i,j,k+1,ismpl) - temp(i,j,k,ismpl) + qz = -lk(i,j,k,ismpl)*dif + END IF + RETURN + END + +!> @brief calculate x heat flux at cell centers +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qxc(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + DOUBLE PRECISION d1, d2, li, amean + integer :: ismpl + integer :: i, j, k + EXTERNAL li, amean + + qxc = 0.D0 + IF (i0<=1) RETURN + IF (i>1 .AND. i<i0) THEN + d1 = temp(i+1,j,k,ismpl) - temp(i,j,k,ismpl) + d2 = temp(i,j,k,ismpl) - temp(i-1,j,k,ismpl) + qxc = amean(-li(i,j,k,ismpl)*d1,-li(i-1,j,k,ismpl)*d2) + ELSE IF (i==1) THEN + qxc = -li(i,j,k,ismpl)*(temp(i+1,j,k,ismpl)-temp(i,j,k,ismpl & + )) + ELSE IF (i==i0) THEN + qxc = -li(i-1,j,k,ismpl)*(temp(i,j,k,ismpl)-temp(i-1,j,k, & + ismpl)) + END IF + RETURN + END + +!> @brief calculate y heat fluxat cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qyc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION d1, d2, lj, amean + EXTERNAL lj, amean + + qyc = 0.D0 + IF (j0<=1) RETURN + IF (j>1 .AND. j<j0) THEN + d1 = temp(i,j+1,k,ismpl) - temp(i,j,k,ismpl) + d2 = temp(i,j,k,ismpl) - temp(i,j-1,k,ismpl) + qyc = amean(-lj(i,j,k,ismpl)*d1,-lj(i,j-1,k,ismpl)*d2) + ELSE IF (j==1) THEN + qyc = -lj(i,j,k,ismpl)*(temp(i,j+1,k,ismpl)-temp(i,j,k,ismpl & + )) + ELSE IF (j==j0) THEN + qyc = -lj(i,j-1,k,ismpl)*(temp(i,j,k,ismpl)-temp(i,j-1,k, & + ismpl)) + END IF + RETURN + END + +!> @brief calculate z heat flux at cell center +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qzc(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION d1, d2, lk, amean + EXTERNAL lk, amean + + qzc = 0.D0 + IF (k0<=1) RETURN + IF (k>1 .AND. k<k0) THEN + d1 = temp(i,j,k+1,ismpl) - temp(i,j,k,ismpl) + d2 = temp(i,j,k,ismpl) - temp(i,j,k-1,ismpl) + qzc = amean(-lk(i,j,k,ismpl)*d1,-lk(i,j,k-1,ismpl)*d2) + ELSE IF (k==1) THEN + qzc = -lk(i,j,k,ismpl)*(temp(i,j,k+1,ismpl)-temp(i,j,k,ismpl & + )) + ELSE IF (k==k0) THEN + qzc = -lk(i,j,k-1,ismpl)*(temp(i,j,k,ismpl)-temp(i,j,k-1, & + ismpl)) + END IF + RETURN + END + +!> @brief average thermal conductivities on cell faces in x direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x thermal conductivity (J/mK) + DOUBLE PRECISION FUNCTION li(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, lx + EXTERNAL lx + + li = 0.D0 + IF (i0>1 .AND. i<i0) THEN + f1 = lx(i,j,k,ismpl) + f2 = lx(i+1,j,k,ismpl) + prod = f1*f2 + summ = f1*delx(i+1) + f2*delx(i) + IF (summ>0.D0) li = 2.D0*prod/summ + END IF +! write(99,'(a,5G14.5)') 'in li ',f1,f2,prod,summ,li + RETURN + END + +!> @brief average thermal conductivities on cell faces in y direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y thermal conductivity (J/mK) + DOUBLE PRECISION FUNCTION lj(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, ly + EXTERNAL ly + + lj = 0.D0 + IF (j0>1 .AND. j<j0) THEN + f1 = ly(i,j,k,ismpl) + f2 = ly(i,j+1,k,ismpl) + prod = f1*f2 + summ = f1*dely(j+1) + f2*dely(j) + IF (summ>0.D0) lj = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief average thermal conductivities on cell faces in z direction +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z thermal conductivity (J/mK,ismpl) + DOUBLE PRECISION FUNCTION lk(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION f1, f2, prod, summ, lz + EXTERNAL lz + + lk = 0.D0 + IF (k0>1 .AND. k<k0) THEN + f1 = lz(i,j,k,ismpl) + f2 = lz(i,j,k+1,ismpl) + prod = f1*f2 + summ = f1*delz(k+1) + f2*delz(k) + IF (summ>0.D0) lk = 2.D0*prod/summ + END IF + RETURN + END + +!> @brief calculate advective heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return x advective heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qvx(i,j,k,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION tcf, vx, rhof, cpf + EXTERNAL vx, rhof, cpf + + qvx = 0.D0 + IF (i0>1 .AND. i<i0) THEN + tcf = (delx(i+1)*temp(i+1,j,k,ismpl)*rhof(i+1,j,k,ismpl)* & + cpf(i+1,j,k,ismpl)+delx(i)*temp(i,j,k,ismpl)*rhof(i,j,k, & + ismpl)*cpf(i,j,k,ismpl))/(delx(i+1)+delx(i)) + qvx = delz(k)*dely(j)*tcf*vx(i,j,k,ismpl) + END IF + RETURN + END + +!> @brief calculate advective heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return y advective heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qvy(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION tcf, vy, rhof, cpf + EXTERNAL vy, rhof, cpf + + qvy = 0.D0 + IF (j0>1 .AND. j<j0) THEN + tcf = (dely(j+1)*temp(i,j+1,k,ismpl)*rhof(i,j+1,k,ismpl)* & + cpf(i,j+1,k,ismpl)+dely(j)*temp(i,j,k,ismpl)*rhof(i,j,k, & + ismpl)*cpf(i,j,k,ismpl))/(dely(j+1)+dely(j)) + qvy = delx(i)*delz(k)*tcf*vy(i,j,k,ismpl) + END IF + RETURN + END + +!> @brief calculate advective heat flux at cell faces +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return z advective heat flux (W/m^2) + DOUBLE PRECISION FUNCTION qvz(i,j,k,ismpl) + use arrays + use mod_genrl + use mod_temp + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + DOUBLE PRECISION tcf, vz, rhof, cpf + EXTERNAL vz, rhof, cpf + + qvz = 0.D0 + IF (k0>1 .AND. k<k0) THEN + tcf = (delz(k+1)*temp(i,j,k+1,ismpl)*rhof(i,j,k+1,ismpl)* & + cpf(i,j,k+1,ismpl)+delz(k)*temp(i,j,k,ismpl)*rhof(i,j,k, & + ismpl)*cpf(i,j,k,ismpl))/(delz(k+1)+delz(k)) + qvz = delx(i)*dely(j)*tcf*vz(i,j,k,ismpl) + END IF + RETURN + END diff --git a/forward/test_opt.f90 b/forward/test_opt.f90 new file mode 100644 index 0000000..b2c068c --- /dev/null +++ b/forward/test_opt.f90 @@ -0,0 +1,100 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief test for a specific runtime option +!> @param[in] soption expected runtime option (string) +!> @return existence of the expected runtime option + LOGICAL FUNCTION test_option(soption) + IMPLICIT NONE + INTEGER i + character (len=80) :: param + character (len=*) :: soption + INTEGER p + + test_option = .FALSE. + i = command_argument_count() + DO p = 1, i + CALL get_command_argument(p,param) + IF (param==soption) THEN + test_option = .TRUE. + RETURN + END IF + END DO + RETURN + END + +!> @brief integer value for a specific runtime option +!> @param[in] soption runtime option (string) +!> @return integer value for the defined runtime option + INTEGER FUNCTION get_ioptval(soption) + IMPLICIT NONE + INTEGER i + character (len=80) :: param + character (len=*) :: soption + INTEGER p, t + + i = command_argument_count() + DO p = 1, i + CALL get_command_argument(p,param) + IF (param==soption) THEN + IF (i>p) THEN + t = p + 1 + CALL get_command_argument(t,param) + READ(param,*) get_ioptval + RETURN + ELSE + WRITE(*,'(3A)') 'error: no option value for "', & + soption, '"!' + STOP + END IF + END IF + END DO + RETURN + END + +!> @brief returns the string value for a specific runtime option +!> @param[in] soption runtime option (string) +!> @param[out] param string value + SUBROUTINE get_coptval(soption,param) + IMPLICIT NONE + INTEGER i + character (len=*) :: param + character (len=*) :: soption + INTEGER p, t + + i = command_argument_count() + DO p = 1, i + CALL get_command_argument(p,param) + IF (param==soption) THEN + IF (i>p) THEN + t = p + 1 + CALL get_command_argument(t,param) + RETURN + ELSE + WRITE(*,'(3A)') 'error: no option value for "', & + soption, '"!' + STOP + END IF + END IF + END DO + RETURN + END diff --git a/hdf5/close_hdf5.f90 b/hdf5/close_hdf5.f90 new file mode 100644 index 0000000..28b72f0 --- /dev/null +++ b/hdf5/close_hdf5.f90 @@ -0,0 +1,56 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief close hdf5-file +!> @details +!> Closing hdf5 files, used in read-routines. +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. + SUBROUTINE close_hdf5() +#ifndef noHDF + USE hdf5 + use mod_input_file_parser_hdf5 + use mod_hdf5_vars, only: default_hdf_file, file_id, error +#endif + IMPLICIT NONE + + +#ifndef noHDF + +! Close hdf5 file. + IF (default_hdf_file/=' ') THEN + CALL h5fclose_f(file_id,error) + END IF + default_hdf_file = ' ' + +! Close FORTRAN interface. + if (.not. h5parse_hdf5_environment) then + CALL h5close_f(error) + end if + +#endif + RETURN + END + diff --git a/hdf5/closeopen_hdf5.f90 b/hdf5/closeopen_hdf5.f90 new file mode 100644 index 0000000..a3d82d2 --- /dev/null +++ b/hdf5/closeopen_hdf5.f90 @@ -0,0 +1,53 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief close and open hdf5-file, when the new one not the default +!> @param[in] f_name hdf5 file name + SUBROUTINE closeopen_hdf5(f_name) +#ifndef noHDF + USE hdf5 + use mod_hdf5_vars, only: default_hdf_file, file_id, error +#endif + IMPLICIT NONE + +! arrayname and filename + character (len=*) :: f_name + +#ifndef noHDF + +! Close and Reopen hdf5 file. + IF (f_name/=default_hdf_file) THEN +! Close hdf5 file. + IF (default_hdf_file/=' ') THEN + CALL h5fclose_f(file_id,error) + END IF +! Reopen hdf5 file. + default_hdf_file = f_name + IF (f_name/=' ') THEN + CALL h5fopen_f(f_name,h5f_acc_rdwr_f,file_id,error) + END IF + END IF + +#endif + RETURN + END + diff --git a/hdf5/mod_hdf5_vars.f90 b/hdf5/mod_hdf5_vars.f90 new file mode 100644 index 0000000..b758256 --- /dev/null +++ b/hdf5/mod_hdf5_vars.f90 @@ -0,0 +1,59 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief shared hdf5 variables +module mod_hdf5_vars + +#ifndef noHDF + + use hdf5, only: hid_t + + !> @brief Name of opened hdf file + !> @details + !> Name of opened hdf file. \n + !> Saves the name of the hdf file opened in open_hdf. + character (len=256) :: default_hdf_file + + !> @brief HDF5 file id + !> @details + !> HDF5 file id. \n + !> HDF5 file id. + integer (kind=hid_t) :: file_id + + + !> @brief HDF5 Error flag + !> @details + !> HDF5 Error flag. \n + !> HDF5 Error flag to check operation success. +#ifdef HDF6432 + integer (kind=4) :: error +#else +#ifdef HDF64 + integer (kind=8) :: error +#else + integer :: error +#endif +#endif + +#endif + +end module mod_hdf5_vars diff --git a/hdf5/mod_input_file_parser_hdf5.f90 b/hdf5/mod_input_file_parser_hdf5.f90 new file mode 100644 index 0000000..18f18da --- /dev/null +++ b/hdf5/mod_input_file_parser_hdf5.f90 @@ -0,0 +1,388 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief hdf5 input file parsing +!> @details +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. +module mod_input_file_parser_hdf5 + ! HDF5 input data format parser + ! Developed as part of the EoCoE project 2016 + ! author: Sebastian Luehrs, JSC, Forschungszentrum Juelich +#ifndef noHDF + use hdf5 +#ifdef fMPI + use mpi +#endif + implicit none + ! globally available information, if HDF5 input file is used + logical :: h5parse_use_hdf5_datafile = .false. + logical :: h5parse_hdf5_environment = .false. + integer(kind=HID_T) :: file_id + private + public :: h5parse_read_dimension_size_for_dataset, h5parse_read_2d_double_dataset, & + & h5parse_read_1d_double_dataset, h5parse_use_hdf5_datafile, & + & h5parse_open_datafile, h5parse_close_datafile, h5parse_check_attr_exist, & + & h5parse_read_double_attribute, h5parse_read_integer_attribute, & + & h5parse_check_dataset_exist, h5parse_read_2d_integer_dataset, & + & h5parse_read_3d_double_dataset, h5parse_read_3d_integer_dataset, & + & h5parse_hdf5_environment +contains + + subroutine h5parse_init() + ! Initalize HDF5 Fortran interface + integer(kind=4) :: hdferr + call H5open_f(hdferr) + h5parse_hdf5_environment = .true. + end subroutine h5parse_init + + subroutine h5parse_open_file(filename) + ! Open HDF5-datafile and store the filehandle + ! @param[in] filename: Input filename + character(len=80), intent(in) :: filename + integer(kind=HID_T) :: plist_id + integer(kind=4) :: hdferr +#ifdef fMPI + ! set up file access propterty for parallel HDF5 + call H5Pcreate_f(H5P_FILE_ACCESS_F, plist_id, hdferr) + call H5Pset_fapl_mpio_f(plist_id,MPI_COMM_WORLD,MPI_INFO_NULL,hdferr) +#else + plist_id = H5P_DEFAULT_F +#endif + ! create new file collectively and release property list identifier + call H5Fopen_f(filename,H5F_ACC_RDONLY_F,file_id,hdferr,plist_id) +#ifdef fMPI + call H5Pclose_f(plist_id,hdferr) +#endif + end subroutine h5parse_open_file + + function h5parse_read_dimension_size_for_dataset(dataset_name,dimension) result(dimension_size) + ! Return the dimension size for a specific dataset (given by name). + ! If the rank of the choosen dataset is > 1, the specific dimension can be selected by number. + ! @param[in] dataset_name: The name of the dataset + ! @param[in] dimension: The dimension number (default: 1) + ! @param[out] dimension_size: Size of the selected dimension in dataset + character(len=*), intent(in) :: dataset_name + integer, intent(in), optional :: dimension + integer :: dimension_size + integer(kind=HID_T) :: dataset_id + integer(kind=HID_T) :: dataspace_id + integer(kind=HSIZE_T), dimension(:), allocatable :: dimsr, maxdimsr + integer(kind=4) :: rank + integer(kind=4) :: hdferr + call H5Dopen_f(file_id,dataset_name,dataset_id,hdferr) + ! Open dataset + call H5Dget_space_f(dataset_id, dataspace_id, hdferr) + ! Get rank + call H5Sget_simple_extent_ndims_f(dataspace_id, rank, hdferr) + allocate(dimsr(rank)) + allocate(maxdimsr(rank)) + ! Get dimension size + call H5Sget_simple_extent_dims_f(dataspace_id, dimsr, maxdimsr, hdferr) + if (present(dimension)) then + dimension_size = int(dimsr(dimension)) + else + dimension_size = int(dimsr(1)) + end if + deallocate(dimsr) + deallocate(maxdimsr) + call H5Sclose_f(dataspace_id, hdferr) + call H5Dclose_f(dataset_id, hdferr) + end function h5parse_read_dimension_size_for_dataset + + subroutine h5parse_read_3d_double_dataset(dataset_name,storage,data_shape_ext) + ! Read a 3D double dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + double precision, dimension(:,:,:), intent(inout) :: storage + integer, optional, dimension(3), intent(in) :: data_shape_ext + integer(kind=HSIZE_T), dimension(3) :: data_shape + if (present(data_shape_ext)) then + data_shape = data_shape_ext + else + data_shape = shape(storage) + end if + call h5parse_read_nd_double_dataset(dataset_name,storage,data_shape) + end subroutine h5parse_read_3d_double_dataset + + subroutine h5parse_read_3d_integer_dataset(dataset_name,storage,data_shape_ext) + ! Read a 3D integer dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + integer, dimension(:,:,:), intent(inout) :: storage + integer, optional, dimension(3), intent(in) :: data_shape_ext + integer(kind=HSIZE_T), dimension(3) :: data_shape + if (present(data_shape_ext)) then + data_shape = data_shape_ext + else + data_shape = shape(storage) + end if + call h5parse_read_nd_integer_dataset(dataset_name,storage,data_shape) + end subroutine h5parse_read_3d_integer_dataset + + subroutine h5parse_read_2d_double_dataset(dataset_name,storage,data_shape_ext) + ! Read a 2D double dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + double precision, dimension(:,:), intent(inout) :: storage + integer, optional, dimension(2), intent(in) :: data_shape_ext + integer(kind=HSIZE_T), dimension(2) :: data_shape + if (present(data_shape_ext)) then + data_shape = data_shape_ext + else + data_shape = shape(storage) + end if + call h5parse_read_nd_double_dataset(dataset_name,storage,data_shape) + end subroutine h5parse_read_2d_double_dataset + + subroutine h5parse_read_2d_integer_dataset(dataset_name,storage,data_shape_ext) + ! Read a 2D integer dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + integer, dimension(:,:), intent(inout) :: storage + integer, optional, dimension(2), intent(in) :: data_shape_ext + integer(kind=HSIZE_T), dimension(2) :: data_shape + if (present(data_shape_ext)) then + data_shape = data_shape_ext + else + data_shape = shape(storage) + end if + call h5parse_read_nd_integer_dataset(dataset_name,storage,data_shape) + end subroutine h5parse_read_2d_integer_dataset + + subroutine h5parse_read_1d_double_dataset(dataset_name,storage,data_shape_ext) + ! Read a 1D double dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + double precision, dimension(:), intent(inout) :: storage + integer, optional, intent(in) :: data_shape_ext + integer(kind=HSIZE_T), dimension(1) :: data_shape + if(present(data_shape_ext))then + data_shape = data_shape_ext + else + data_shape = shape(storage) + end if + call h5parse_read_nd_double_dataset(dataset_name,storage,data_shape) + end subroutine h5parse_read_1d_double_dataset + + subroutine h5parse_read_nd_double_dataset(dataset_name,storage,data_shape) + ! Read a nD double dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + double precision, dimension(*), intent(inout) :: storage + integer(kind=HSIZE_T), dimension(:), intent(in) :: data_shape + integer(kind=HSIZE_T), dimension(:), allocatable :: offset + integer(kind=HID_T) :: dataset_id + integer(kind=HID_T) :: dataspace_id, memspace_id + integer(kind=4) :: hdferr + allocate(offset(size(data_shape))) + offset = 0 + call H5Dopen_f(file_id, dataset_name, dataset_id, hdferr) + ! Open dataset + call H5Dget_space_f(dataset_id, dataspace_id, hdferr) + ! Select data_shape in dataset + call H5Sselect_hyperslab_f(dataspace_id, H5S_SELECT_SET_F, offset, data_shape, hdferr) + ! Create memory dataspace + call H5Screate_simple_f(size(data_shape), data_shape, memspace_id, hdferr) + ! Read the data + call H5Dread_f(dataset_id, H5T_NATIVE_DOUBLE, storage, data_shape, hdferr, & + & memspace_id, dataspace_id) + call H5Sclose_f(memspace_id, hdferr) + call H5Sclose_f(dataspace_id, hdferr) + call H5Dclose_f(dataset_id, hdferr) + deallocate(offset) + end subroutine h5parse_read_nd_double_dataset + + subroutine h5parse_read_nd_integer_dataset(dataset_name,storage,data_shape) + ! Read a nD integer dataset + ! @param[in] dataset_name: The name of the dataset + ! @param[inout] storage: Storage array which will hold the the contents of the dataset + ! @param[in] data_shape_ext: Selectable file data_shape (default: shape of storage) + character(len=*), intent(in) :: dataset_name + integer, dimension(*), intent(inout) :: storage + integer(kind=HSIZE_T), dimension(:), intent(in) :: data_shape + integer(kind=HSIZE_T), dimension(:), allocatable :: offset + integer(kind=HID_T) :: dataset_id + integer(kind=HID_T) :: dataspace_id, memspace_id + integer(kind=4) :: hdferr + allocate(offset(size(data_shape))) + offset = 0 + call H5Dopen_f(file_id,dataset_name,dataset_id,hdferr) + ! Open dataset + call H5Dget_space_f(dataset_id, dataspace_id, hdferr) + ! Select data_shape in dataset + call H5Sselect_hyperslab_f(dataspace_id, H5S_SELECT_SET_F, offset, data_shape, hdferr) + ! Create memory dataspace + call H5Screate_simple_f(size(data_shape), data_shape, memspace_id, hdferr) + ! Read the data + call H5Dread_f(dataset_id, H5T_NATIVE_INTEGER, storage, data_shape, hdferr, & + & memspace_id, dataspace_id) + call H5Sclose_f(memspace_id, hdferr) + call H5Sclose_f(dataspace_id, hdferr) + call H5Dclose_f(dataset_id, hdferr) + deallocate(offset) + end subroutine h5parse_read_nd_integer_dataset + + function h5parse_check_attr_exist(attr_name,obj_name_ext) result(attr_exists) + ! Check if a specifc attribute, given by name, exists + ! @param[in] attr_name: The name of the attribute + ! @param[in] obj_name_ext: The relative context the attribute belongs to (default: root) + ! @param[out] attr_exists: Attribute exists? + character(len=*), intent(in) :: attr_name + character(len=*), optional, intent(in) :: obj_name_ext + character(len=255) :: obj_name + logical(kind=4) :: attr_exists + integer(kind=4) :: hdferr + if(present(obj_name_ext)) then + obj_name = obj_name_ext + else + obj_name = "/" + end if + call h5aexists_by_name_f(file_id, obj_name, attr_name, attr_exists, hdferr) + end function h5parse_check_attr_exist + + function h5parse_check_dataset_exist(dataset_name) result(dataset_exists) + ! Check if a specifc dataset, given by name, exists + ! @param[in] dataset_name: The name of the dataset + ! @param[out] dataset_exists: Dataset exists? + character(len=*), intent(in) :: dataset_name + logical(kind=4) :: dataset_exists + integer(kind=4) :: hdferr + call h5lexists_f(file_id, dataset_name, dataset_exists, hdferr) + end function h5parse_check_dataset_exist + + subroutine h5parse_read_double_attribute(attr_name,storage,obj_name_ext) + ! Read the content of a double attribute + ! @param[in] attr_name: The name of the attribute + ! @param[in] obj_name_ext: The relative context the attribute belongs to (default: root) + ! @param[inout] storage: Storage variable which will hold the the content of the attribute + character(len=*), intent(in) :: attr_name + double precision, intent(inout) :: storage + character(len=*), optional, intent(in) :: obj_name_ext + character(len=255) :: obj_name + integer(kind=4) :: hdferr + integer(kind=HID_T) :: attr_id + integer(kind=HSIZE_T), dimension(1) :: dims = 0 + if(present(obj_name_ext)) then + obj_name = obj_name_ext + else + obj_name = "/" + end if + call h5aopen_by_name_f(file_id, obj_name, attr_name, attr_id, hdferr) + call h5aread_f(attr_id, H5T_NATIVE_DOUBLE, storage, dims, hdferr) + call h5aclose_f(attr_id, hdferr) + end subroutine h5parse_read_double_attribute + + subroutine h5parse_read_integer_attribute(attr_name,storage,obj_name_ext) + ! Read the content of a integer attribute + ! @param[in] attr_name: The name of the attribute + ! @param[in] obj_name_ext: The relative context the attribute belongs to (default: root) + ! @param[inout] storage: Storage variable which will hold the the content of the attribute + character(len=*), intent(in) :: attr_name + integer, intent(inout) :: storage + character(len=*), optional, intent(in) :: obj_name_ext + character(len=255) :: obj_name + integer(kind=4) :: hdferr + integer(kind=HID_T) :: attr_id + integer(kind=HSIZE_T), dimension(1) :: dims = 0 + if(present(obj_name_ext)) then + obj_name = obj_name_ext + else + obj_name = "/" + end if + call h5aopen_by_name_f(file_id, obj_name, attr_name, attr_id, hdferr) + call h5aread_f(attr_id, H5T_NATIVE_INTEGER, storage, dims, hdferr) + call h5aclose_f(attr_id, hdferr) + end subroutine h5parse_read_integer_attribute + + subroutine h5parse_close_file() + ! Close the HDF5 internal file handle + integer(kind=4) :: hdferr + call H5Fclose_f(file_id, hdferr) + end subroutine h5parse_close_file + + subroutine h5parse_finalize() + ! Close the HDF5 Fortran interface + integer(kind=4) :: hdferr + h5parse_hdf5_environment = .false. + call H5close_f(hdferr) + end subroutine h5parse_finalize + + subroutine h5parse_open_datafile(filename) + ! Find the HDF5 datafile filenam in the standard ASCII input file + ! @param[in] filename: Name of the standard ASCII input file + use mod_genrl + character(len=*), intent(in) :: filename + character(len=255) :: hdf5_data_filename + character(len=80) :: line + logical :: found + integer :: lblank + open(79,file=filename,status='old') + call h5parse_init() + ! Search for the HDF5 datafile filename + if (found(79,key_char//' h5parse data file',line,.false.)) then + read(79,'(1A)',err=200,end=200) hdf5_data_filename + write(*,*) ' ' + write(*,*) ' reading model input data:' + write(*,*) ' from file "', hdf5_data_filename(& + &:lblank(hdf5_data_filename)),'"' + write(*,*) ' ' + ! Use HDF5 input file parser + h5parse_use_hdf5_datafile = .true. + ! Open the datafile + call h5parse_open_file(hdf5_data_filename) + else + ! Do not use HDF5 input file parser (use old input format) + h5parse_use_hdf5_datafile = .false. + end if + close(79) + return +200 write(*,'(1A)') 'error: can not read "h5parse data file"!' + stop + end subroutine h5parse_open_datafile + + subroutine h5parse_close_datafile() + ! Close the HDF5 internal file handle and the HDF5 interface + if (h5parse_use_hdf5_datafile) then + call h5parse_close_file() + h5parse_use_hdf5_datafile = .false. + end if + call h5parse_finalize() + end subroutine h5parse_close_datafile +#endif + +end module mod_input_file_parser_hdf5 diff --git a/hdf5/open_hdf5.f90 b/hdf5/open_hdf5.f90 new file mode 100644 index 0000000..9f48757 --- /dev/null +++ b/hdf5/open_hdf5.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief open hdf5-file +!> @param[in] f_name hdf5 file name +!> @details +!> Opening hdf5 files, used in read-routines. +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. + SUBROUTINE open_hdf5(f_name) +#ifndef noHDF + USE hdf5 + use mod_input_file_parser_hdf5 + use mod_hdf5_vars, only: default_hdf_file, file_id, error +#endif + IMPLICIT NONE + +! arrayname and filename + character (len=*) :: f_name + + +#ifndef noHDF + +! Initialize FORTRAN interface. + if (.not. h5parse_hdf5_environment) then + CALL h5open_f(error) + end if + +! Reopen hdf5 file. + default_hdf_file = f_name + IF (f_name/=' ') THEN + CALL h5fopen_f(f_name,h5f_acc_rdwr_f,file_id,error) + END IF + +#endif + RETURN + END + diff --git a/hdf5/read_hdf5.f90 b/hdf5/read_hdf5.f90 new file mode 100644 index 0000000..a661393 --- /dev/null +++ b/hdf5/read_hdf5.f90 @@ -0,0 +1,117 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +! ****************************************************** +! WARNING: need 32 Bit version of the HDF5 library ! +! ****************************************************** + +!> @brief reads an 3-dimensional array HDF5 file +!> @param[in] NI 1.dimension +!> @param[in] NJ 2.dimension +!> @param[in] NK 3.dimension +!> @param[in] A_name array name +!> @param[in] f_name hdf5 file name +!> @param[out] A double precision array with all readed data +!> @details +!> This routine is used to open external hdf5 files specified in +!> the SHEMAT-Suite input file and read a double precision array. + SUBROUTINE read_hdf5(ni,nj,nk,a,a_name,f_name) +#ifndef noHDF + USE hdf5 + use mod_hdf5_vars, only: file_id, error +#endif + use mod_linfos + IMPLICIT NONE + +! arrayname and filename + character (len=*) :: a_name, f_name + + INTEGER ni, nj, nk + DOUBLE PRECISION a(ni,nj,nk) + +#ifndef noHDF +! Dataset identifier + INTEGER (hid_t) dset_id + +! Data type identifier + INTEGER (hid_t) dtype_id +#endif + +#ifndef noHDF +! Data buffers + INTEGER (hsize_t) data_dims(7) +#endif + +#ifndef noHDF + + data_dims(1) = ni + data_dims(2) = nj + data_dims(3) = nk + +! Open hdf5 file if closed + CALL closeopen_hdf5(f_name) + +! Access dataset 'A' in the first file under 'A_name' name. + CALL h5dopen_f(file_id,a_name,dset_id,error) + + IF (error/=0) THEN + WRITE(*,*) + WRITE(*,'(5A)') 'error: no array "', a_name, & + '" on the file "', f_name, '" !!!' + IF (a_name=='head') THEN + WRITE(*,'(2A)') '*** May be an old "phi" style file,', & + ' then change it to "head" ! ***' + WRITE(*,'(1A)') ' -> try to find "phi" ...' + WRITE(*,*) + CALL h5dopen_f(file_id,'phi',dset_id,error) + GO TO 300 + END IF + WRITE(*,*) + STOP + END IF +300 CONTINUE + +! Get dataset's data type. + CALL h5dget_type_f(dset_id,dtype_id,error) + +! Read the dataset in 'A'. +!AW call h5dread_f(dset_id, dtype_id, A, data_dims, error) + CALL h5dread_f(dset_id,h5t_native_double,a,data_dims,error) + + IF (error/=0) THEN + WRITE(*,'(5A)') 'error: can not read the array "', a_name, & + '" on the file "', f_name, '" !' + STOP + END IF + +! Close file, dataset and dataspace identifiers. + CALL h5dclose_f(dset_id,error) + CALL h5tclose_f(dtype_id,error) + + IF (linfos(1)>=1) WRITE(*,*) ' open HDF5 file: ', f_name + +#else + WRITE(*,*) 'error: HDF5 support was not compiled in' + STOP +#endif + RETURN + END diff --git a/hdf5/read_hdf5_int.f90 b/hdf5/read_hdf5_int.f90 new file mode 100644 index 0000000..ed2b74e --- /dev/null +++ b/hdf5/read_hdf5_int.f90 @@ -0,0 +1,127 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief reads an 3-dimensional array from an opened HDF5 file +!> @param[in] NI 1.dimension +!> @param[in] NJ 2.dimension +!> @param[in] NK 3.dimension +!> @param[in] A_name array name +!> @param[in] f_name hdf5 file name +!> @param[out] A integer array with all readed data +!> This routine is used to open external hdf5 files specified in +!> the SHEMAT-Suite input file and read a integer array. + SUBROUTINE read_hdf5_int(ni,nj,nk,a,a_name,f_name) +#ifndef noHDF + USE hdf5 + use mod_hdf5_vars, only: file_id, error +#endif + use mod_linfos + IMPLICIT NONE + +! arrayname and filename + character (len=*) :: a_name, f_name + + INTEGER ni, nj, nk, i, j, k + INTEGER a(ni,nj,nk) + +#ifndef noHDF +! Dataset identifier + INTEGER (hid_t) dset_id + +! Data type identifier + INTEGER (hid_t) dtype_id +#endif + +#ifndef noHDF +! Data buffers + INTEGER (hsize_t) data_dims(7) +#endif + +! for 32Bit HDF5 library +#ifdef HDF6432 + INTEGER (kind=4), allocatable :: inttmp(:,:,:) +#else +#ifdef HDF64 + INTEGER (kind=8), allocatable :: inttmp(:,:,:) +#else + INTEGER, ALLOCATABLE :: inttmp(:,:,:) +#endif +#endif + +#ifndef noHDF + + ALLOCATE(inttmp(ni,nj,nk)) + + data_dims(1) = ni + data_dims(2) = nj + data_dims(3) = nk + +! Open hdf5 file if closed + CALL closeopen_hdf5(f_name) + +! Access dataset 'A' in the first file under 'A_name' name. + CALL h5dopen_f(file_id,a_name,dset_id,error) + + IF (error/=0) THEN + WRITE(*,*) + WRITE(*,'(5A)') 'error: no array "', a_name, & + '" on the file "', f_name, '" !!!' + WRITE(*,*) + STOP + END IF + +! Get dataset's data type. + CALL h5dget_type_f(dset_id,dtype_id,error) + +! Read the dataset in 'A'. +!AW call h5dread_f(dset_id, dtype_id, A, data_dims, error) + CALL h5dread_f(dset_id,h5t_native_integer,inttmp,data_dims, & + error) + + IF (error/=0) THEN + WRITE(*,'(5A)') 'error: can not read the array "', a_name, & + '" on the file "', f_name, '" !' + STOP + END IF + +! Close file, dataset and dataspace identifiers. + CALL h5dclose_f(dset_id,error) + CALL h5tclose_f(dtype_id,error) + DO k = 1, nk + DO j = 1, nj + DO i = 1, ni + a(i,j,k) = inttmp(i,j,k) + END DO + END DO + END DO + + DEALLOCATE(inttmp) + + IF (linfos(1)>=1) WRITE(*,*) ' open HDF5 file: ', f_name + +#else + WRITE(*,*) 'error: HDF5 support was not compiled in' + STOP +#endif + RETURN + END + diff --git a/hdf5/test_hdf5.f90 b/hdf5/test_hdf5.f90 new file mode 100644 index 0000000..182cdb1 --- /dev/null +++ b/hdf5/test_hdf5.f90 @@ -0,0 +1,32 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief flag function (HDF5 enabled) +!> @return logical switch for hdf environment variable + LOGICAL FUNCTION test_hdf5() +#ifndef noHDF + test_hdf5 = .TRUE. +#else + test_hdf5 = .FALSE. +#endif + RETURN + END diff --git a/hdf5/write_all_hdf5.f90 b/hdf5/write_all_hdf5.f90 new file mode 100644 index 0000000..4fe5770 --- /dev/null +++ b/hdf5/write_all_hdf5.f90 @@ -0,0 +1,698 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +! ****************************************************** +! WARNING: need 32 Bit version of the HDF5 library ! +! ****************************************************** + +!> @brief write out the physical state and all properties +!> @param[in] ident file/iteration index number +!> @param[in] ismpl local sample index +!> @details +!> create an hdf5 output file\n + SUBROUTINE write_hdf(ident,ismpl) +#ifndef noHDF + USE hdf5 + use mod_hdf5_vars, only: error +#endif + use arrays + use mod_genrl + use mod_genrlc + use mod_flow + use mod_temp + use mod_conc + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + double precision :: dx, dy, dz + integer :: i1s, i2s, i1, i2, i3, i4, ident + + double precision, external :: vxc, vyc, vzc, kx, ky, kz, lx, ly, lz, por, & + rhof, visf + + character (len=80) :: filename + character (len=8) :: snumber + + logical, dimension (3) :: out_bc + +#ifndef noHDF +! File identifiers + integer (kind=hid_t) :: file_id + +! Dataset identifier + integer (kind=hid_t) :: dset_id + +! Data space identifier + integer (kind=hid_t) :: dataspace +#endif + +#ifdef HDF6432 +! need for 32Bit HDF5 library + INTEGER (kind=4) :: rank + INTEGER (kind=4) :: gzlevel + INTEGER (kind=4), allocatable :: inttmp(:,:,:) +#else +#ifdef HDF64 + INTEGER (kind=8) :: rank + INTEGER (kind=8) :: gzlevel + INTEGER (kind=8), allocatable :: inttmp(:,:,:) +#else + integer :: rank + integer :: gzlevel + integer, allocatable, dimension (:,:,:) :: inttmp +#endif +#endif + PARAMETER (rank=3) + +! gzip compression level + PARAMETER (gzlevel=9) + +#ifndef noHDF +! Data buffers + integer (kind=hsize_t), dimension (rank) :: dims + integer (kind=hsize_t), dimension (7) :: data_dims + +! for chunk size and compression + integer (kind=hid_t) :: plist_id + integer (kind=hsize_t), dimension (rank) :: chunk_dims +#endif + + DOUBLE PRECISION, ALLOCATABLE :: dp3tmp(:,:,:), & + dp4tmp(:,:,:,:) + +! bc-naming + character (len=3), dimension (2) :: c_bt + DATA c_bt/'bcd', 'bcn'/ + character (len=8) :: c_name + + integer, external :: lblank + +#ifndef noHDF + +#ifdef NOOUT + RETURN +#endif + + CALL chln(project,i1,i2) + CALL chln(project_sfx(ismpl),i1s,i2s) + IF (ident>=0) THEN + WRITE(snumber,'(1I7)') ident + ELSE IF (ident==-1) THEN + WRITE(snumber,'(A8)') 'final' + ELSE IF (ident==-2) THEN + WRITE(snumber,'(A8)') 'debug' + ELSE IF (ident==-3) THEN + WRITE(snumber,'(A8)') 'ens_mean' + ELSE IF (ident==-4) THEN + WRITE(snumber,'(A8)') 'mean' + ELSE IF (ident==-5) THEN + WRITE(snumber,'(A8)') 'ens_mean' + END IF + CALL chln(snumber,i3,i4) + IF (i1s==0) THEN + filename = project(i1:i2) // '_' // snumber(i3:i4) // '.h5' + ELSE + filename = project(i1:i2) // project_sfx(ismpl) (i1s:i2s) // & + '_' // snumber(i3:i4) // '.h5' + END IF + + IF (linfos(3)>=1) THEN + WRITE(*,'(3A)') ' [W] : HDF5 to "', & + filename(1:lblank(filename)), '"' + END IF + + +#ifdef fOMP +!$OMP critical +#endif +! Initialize FORTRAN interface. + CALL h5open_f(error) + +! Create a new file, later only open it for read and writes + CALL h5fcreate_f(filename,h5f_acc_trunc_f,file_id,error, & + h5p_default_f,h5p_default_f) + + dims(1) = i0 + dims(2) = j0 + dims(3) = k0 + data_dims(1) = i0 + data_dims(2) = j0 + data_dims(3) = k0 + chunk_dims(1) = min(20,i0) + chunk_dims(2) = min(20,j0) + chunk_dims(3) = min(20,k0) + +! for compression only + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + ALLOCATE(inttmp(i0,j0,k0)) + ALLOCATE(dp4tmp(i0,j0,k0,7)) +! not very performant !!! + DO i3 = 1, k0 + dz = delza(i3) + DO i2 = 1, j0 + dy = delya(i2) + DO i1 = 1, i0 + dx = delxa(i1) + dp4tmp(i1,i2,i3,1) = dx + dp4tmp(i1,i2,i3,2) = dy + dp4tmp(i1,i2,i3,3) = dz + dp4tmp(i1,i2,i3,4) = vxc(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,5) = vyc(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,6) = vzc(i1,i2,i3,ismpl) + END DO + END DO + END DO + + IF (ident<=-1 .OR. out_ijk(cout_i)) THEN +! Create data space for the dataset. + CALL h5screate_simple_f(rank,dims,dataspace,error) +! Create dataset "A" inside file "f_name". + CALL h5dcreate_f(file_id,'x',h5t_native_double,dataspace, & + dset_id,error,plist_id) +! Write 'A' to the dataset + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,1), & + data_dims,error) +! Close file, dataset and dataspace identifiers. + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_ijk(cout_j)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'y',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,2), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_ijk(cout_k)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'z',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,3), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + inttmp(i1,i2,i3) = uindex(i1,i2,i3) + END DO + END DO + END DO + IF (ident<=-1 .OR. out_ijk(cout_uindex)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'uindex',h5t_native_integer, & + dataspace,dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_integer,inttmp,data_dims, & + error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + +! - main arrays - + IF (ident<=-1 .OR. out_pv(pv_head)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'head',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,head(1,1,1,ismpl), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_pv(pv_temp)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'temp',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,temp(1,1,1,ismpl), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_pv(pv_pres)) THEN +! convert [Pa] into [MPa] + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + x(i1,i2,i3,ismpl) = pres(i1,i2,i3,ismpl)*pa_conv1 + END DO + END DO + END DO + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'pres',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,x(1,1,1,ismpl), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF ((ident<=-1 .OR. out_pv(pv_conc)) .AND. trans_active) THEN + DO i = 1, ntrans + WRITE(snumber,'(1A4,1I4.4)') 'conc', i + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,snumber,h5t_native_double, & + dataspace,dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double, & + conc(1,1,1,i,ismpl),data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END DO + END IF + +! --------------- + + IF (ident<=-1 .OR. out_ijk(cout_vx)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'vx',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,4), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_ijk(cout_vy)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'vy',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,5), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_ijk(cout_vz)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'vz',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,6), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + dp4tmp(i1,i2,i3,7) = por(i1,i2,i3,ismpl) + END DO + END DO + END DO + IF (ident<=-1 .OR. out_prop(idx_por)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'por',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,7), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + dp4tmp(i1,i2,i3,1) = kx(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,2) = ky(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,3) = kz(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,4) = lx(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,5) = ly(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,6) = lz(i1,i2,i3,ismpl) + END DO + END DO + END DO + IF (ident<=-1 .OR. out_prop(idx_an_kx)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'kx',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,1), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_an_ky)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'ky',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,2), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_kz)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'kz',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,3), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_an_lx)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'lx',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,4), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_an_ly)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'ly',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,5), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_lz)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'lz',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,6), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + i = uindex(i1,i2,i3) + dp4tmp(i1,i2,i3,1) = propunit(i,idx_comp,ismpl) + dp4tmp(i1,i2,i3,2) = propunit(i,idx_q,ismpl) + dp4tmp(i1,i2,i3,3) = propunit(i,idx_rc,ismpl) + dp4tmp(i1,i2,i3,4) = propunit(i,idx_df,ismpl) + dp4tmp(i1,i2,i3,5) = propunit(i,idx_ec,ismpl) + dp4tmp(i1,i2,i3,6) = propunit(i,idx_lc,ismpl) + END DO + END DO + END DO + + IF (ident<=-1 .OR. out_prop(idx_comp)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'comp',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,1), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_q)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'q',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,2), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_rc)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'rc',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,3), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_df)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'df',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,4), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_ec)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'ec',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,5), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_prop(idx_lc)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'lc',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,6), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + + DO i3 = 1, k0 + DO i2 = 1, j0 + DO i1 = 1, i0 + dp4tmp(i1,i2,i3,1) = rhof(i1,i2,i3,ismpl) + dp4tmp(i1,i2,i3,2) = visf(i1,i2,i3,ismpl) + END DO + END DO + END DO + IF (ident<=-1 .OR. out_ijk(cout_rhof)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'rhof',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,1), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + IF (ident<=-1 .OR. out_ijk(cout_visf)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'visf',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp4tmp(1,1,1,2), & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + dims(1) = i0 + dims(2) = 1 + dims(3) = 1 + data_dims(1) = i0 + data_dims(2) = 1 + data_dims(3) = 1 + chunk_dims(1) = min(8000,i0) + chunk_dims(2) = 1 + chunk_dims(3) = 1 +! for compression only + CALL h5pclose_f(plist_id,error) + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + IF (out_ijk(cout_i)) THEN +! Create data space for the dataset. + CALL h5screate_simple_f(rank,dims,dataspace,error) +! Create dataset "A" inside file "f_name". + CALL h5dcreate_f(file_id,'delx',h5t_native_double,dataspace, & + dset_id,error,plist_id) +! Write 'A' to the dataset + CALL h5dwrite_f(dset_id,h5t_native_double,delx,data_dims, & + error) +! Close file, dataset and dataspace identifiers. + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + dims(1) = 1 + dims(2) = j0 + dims(3) = 1 + data_dims(1) = 1 + data_dims(2) = j0 + data_dims(3) = 1 + chunk_dims(1) = 1 + chunk_dims(2) = min(8000,j0) + chunk_dims(3) = 1 +! for compression only + CALL h5pclose_f(plist_id,error) + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + IF (out_ijk(cout_j)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'dely',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dely,data_dims, & + error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + dims(1) = 1 + dims(2) = 1 + dims(3) = k0 + data_dims(1) = 1 + data_dims(2) = 1 + data_dims(3) = k0 + chunk_dims(1) = 1 + chunk_dims(2) = 1 + chunk_dims(3) = min(8000,k0) +! for compression only + CALL h5pclose_f(plist_id,error) + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + IF (out_ijk(cout_k)) THEN + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'delz',h5t_native_double,dataspace, & + dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,delz,data_dims, & + error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + + DEALLOCATE(inttmp) + DEALLOCATE(dp4tmp) +! ------------------------------------------------------------------ +! full tables of boundary conditions + + IF (nbc_data>0) THEN + + out_bc(1) = out_prop(idx_hbc) + out_bc(2) = out_prop(idx_tbc) + out_bc(3) = out_prop(idx_cbc) + + DO j = 1, 3 + if (out_bc(j)) then + DO i = 1, 2 + c_name = pv_name(j) // '_' // c_bt(i) +! count the number of bc with this type (i,j) + k = 0 + DO i1 = 1, nbc_data + IF (ibc_data(i1,cbc_pv)==j .AND. & + ibc_data(i1,cbc_bt)==i) k = k + 1 + END DO + ALLOCATE(dp3tmp(k,ndbc,1)) + ALLOCATE(inttmp(k,nibc,1)) +! copy the counted bc + k = 0 + DO i1 = 1, nbc_data + IF (ibc_data(i1,cbc_pv)==j .AND. & + ibc_data(i1,cbc_bt)==i) THEN + k = k + 1 + DO i2 = 1, nibc + inttmp(k,i2,1) = ibc_data(i1,i2) + END DO + DO i2 = 1, ndbc + dp3tmp(k,i2,1) = dbc_data(i1,i2,ismpl) + END DO + END IF + END DO + + IF (k>0) THEN + dims(1) = k + dims(2) = nibc + dims(3) = 1 + data_dims(1) = k + data_dims(2) = nibc + data_dims(3) = 1 +! for compression only + chunk_dims(1) = min(2000,k) + chunk_dims(2) = 1 + chunk_dims(3) = 1 + CALL h5pclose_f(plist_id,error) + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,'i'//c_name, & + h5t_native_integer,dataspace,dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_integer,inttmp, & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + + dims(2) = ndbc + data_dims(2) = ndbc +! for compression only + chunk_dims(1) = min(4000,k) + CALL h5pclose_f(plist_id,error) + CALL h5pcreate_f(h5p_dataset_create_f,plist_id,error) + CALL h5pset_chunk_f(plist_id,rank,chunk_dims,error) + CALL h5pset_deflate_f(plist_id,gzlevel,error) + + CALL h5screate_simple_f(rank,dims,dataspace,error) + CALL h5dcreate_f(file_id,c_name,h5t_native_double, & + dataspace,dset_id,error,plist_id) + CALL h5dwrite_f(dset_id,h5t_native_double,dp3tmp, & + data_dims,error) + CALL h5sclose_f(dataspace,error) + CALL h5dclose_f(dset_id,error) + END IF + DEALLOCATE(inttmp) + DEALLOCATE(dp3tmp) + END DO + end if + END DO + END IF + +! ------------------------------------------------------------------ + +! close interface + CALL h5pclose_f(plist_id,error) + CALL h5fclose_f(file_id,error) + +! close FORTRAN interface + CALL h5close_f(error) + +#ifdef fOMP +!$OMP end critical +#endif + +#endif + RETURN + END diff --git a/props/bas/check_domain.f90 b/props/bas/check_domain.f90 new file mode 100644 index 0000000..4efc925 --- /dev/null +++ b/props/bas/check_domain.f90 @@ -0,0 +1,188 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief domain of validity for module bas +!> @param[in] ismpl local sample index +!> @details +!> Checking whether pres/temp/(conc) are in domain of props +!> validity. Version for property module bas. \n +!> \n +!> For concentration, an error is thrown and the execution is +!> stopped if the concentration is outside the physical values. + subroutine check_domain(ismpl) + use arrays, only: pres, temp, conc + use mod_genrl, only: i0, j0, k0 + use mod_genrlc, only: def_props + use mod_conc, only: ntrac + use mod_linfos, only: linfos + + implicit none + + ! Sample index + integer :: ismpl + + ! Iteration counters + integer :: i, j, k, l + + ! counters for the values outside domain of validity + ! pres + integer :: icountp + ! temp + integer :: icountt + ! conc + integer :: icountc + + ! min/max boundaries of the domain of validity + ! pres + double precision, parameter :: pmin = 0.01d6 + double precision, parameter :: pmax = 110.0d6 + ! temp + double precision, parameter :: tmin = 0.0d0 + double precision, parameter :: tmax = 350.0d0 + ! conc + double precision, parameter :: cmin = 0.0d0 + double precision, parameter :: cmax = 1.0d5 + ! numerical boundary + double precision, parameter :: csmin = 1.0d-22 + + ! records the overall min/max of values if they are outside + ! domain of validity + double precision :: dpmax, dtmax, dcmax, dhmax + double precision :: dpmin, dtmin, dcmin, dhmin + + intrinsic trim + + + ! Set counters to zero + icountp = 0 + icountt = 0 + icountc = 0 + + ! Set overall min/max to boundaries of the domain of validity + dpmax = pmax + dpmin = pmin + dtmax = tmax + dtmin = tmin + dcmax = cmax + dcmin = cmin + + ! Check pres + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (pres(i,j,k,ismpl)<pmin) then + ! Set min counter + icountp = icountp + 1 + ! Set new overall minimum + dpmin = min(dpmin,pres(i,j,k,ismpl)) + ! Change pres value to minimum of the domain of validity + pres(i,j,k,ismpl) = pmin + end if + if (pres(i,j,k,ismpl)>pmax) then + ! Set max counter + icountp = icountp + 1 + ! Set new overall maximum + dpmax = max(dpmax,pres(i,j,k,ismpl)) + ! Change pres value to maximum of the domain of validity + pres(i,j,k,ismpl) = pmax + end if + end do + end do + end do + + ! Check temp + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (temp(i,j,k,ismpl)<tmin) then + icountt = icountt + 1 + dtmin = min(dtmin,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmin + end if + if (temp(i,j,k,ismpl)>tmax) then + icountt = icountt + 1 + dtmax = max(dtmax,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmax + end if + end do + end do + end do + + ! Check conc + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + do l = 1, ntrac + if (conc(i,j,k,l,ismpl).gt.cmax) then + icountc = icountc +1 + dcmax = max(dcmax, conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmax + end if + if (conc(i,j,k,l,ismpl)<cmin .and. & + conc(i,j,k,l,ismpl)<-csmin) then + icountc = icountc + 1 + dcmin = min(dcmin,conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmin + end if + if (conc(i,j,k,l,ismpl)<csmin) then + ! very small conc values set to zero to avoid + ! numerically instabilities + conc(i,j,k,l,ismpl) = cmin + end if + end do + end do + end do + end do + +! disable the warning output for linfos(3)==-1 + if (linfos(3)>=0) then + if (icountp/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: pres not in domain of validity of module <', & + trim(def_props), '> at ', icountp, ' points (min', dpmin, & + ', max', dpmax, ')!' + if (icountt/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: temp not in domain of validity of module <', & + trim(def_props), '> at ', icountt, ' points (min', dtmin, & + ', max', dtmax, ')!' + if (icountc/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: conc not in domain of validity of module <', & + trim(def_props), '> at ', icountc, ' points (min', dcmin, & + ', max', dcmax, ')!' + + ! error outputs for hard physical concentration boundaries + if (dcmax > cmax) then + write(unit = *, fmt = *) "[E1] Error in check_domain.f90:", & + " maximum concentration dcmax= ", dcmax, & + " larger than allowed maximum value cmax=", cmax + stop + end if + if (dcmin > cmin) then + write(unit = *, fmt = *) "[E2] Error in check_domain.f90:", & + " minimum concentration dcmin= ", dcmin, & + " smaller than allowed minimum value cmin=", cmin + stop + end if + end if + + return + + end subroutine check_domain diff --git a/props/bas/compf.f90 b/props/bas/compf.f90 new file mode 100644 index 0000000..78ec758 --- /dev/null +++ b/props/bas/compf.f90 @@ -0,0 +1,192 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compf calculates compressibility of pure water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility compf [1./Pa] +!> @details +!> compf calculates compressibility of pure water \n +!> given temperature (t, in C), and pressure (p,in Pa)\n +!> at node(i,j,k).\n \n +!> +!> Method: \n +!> +!> compf = 1/rhof d/dP rhof, \n +!> +!> where rhof= water density.\n \n +!> +!> Main source of rhof (water density) approximation, see +!> props/bas/rhof.f90. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function compf(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv, pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.10000000D+01 + double precision, parameter :: Y1 = 0.17472599D-01 + double precision, parameter :: Y2 = -0.20443098D-04 + double precision, parameter :: Y3 = -0.17442012D-06 + double precision, parameter :: Y4 = 0.49564109D-02 + double precision, parameter :: Y5 = -0.40757664D-04 + double precision, parameter :: Y6 = 0.50676664D-07 + double precision, parameter :: Y7 = 0.50330978D-04 + double precision, parameter :: Y8 = 0.33914814D-06 + double precision, parameter :: Y9 = -0.18383009D-06 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10009476D-02 + double precision, parameter :: Z1 = 0.16812589D-04 + double precision, parameter :: Z2 = -0.24582622D-07 + double precision, parameter :: Z3 = -0.17014984D-09 + double precision, parameter :: Z4 = 0.48841156D-05 + double precision, parameter :: Z5 = -0.32967985D-07 + double precision, parameter :: Z6 = 0.28619380D-10 + double precision, parameter :: Z7 = 0.53249055D-07 + double precision, parameter :: Z8 = 0.30456698D-09 + double precision, parameter :: Z9 = -0.12221899D-09 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt P + double precision :: da + + ! Derivative of denominator wrt P + double precision :: db + + ! Denominator squared + double precision :: b2 + + ! Water density (local) + double precision :: rhof_loc + + ! Derivative of water density wrt P + double precision :: drhodp + + ! Compressibiliy in Mpa + double precision :: compf_mpa + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Water density + rhof_loc = ta/tb + + ! Derivative of numerator + da = Y1 + 2.D0*Y2*p + 3.D0*Y3*p2 + Y7*t + & + 2.D0*Y8*tp + Y9*t2 + + ! Derivative of denominator + db = Z1 + 2.D0*Z2*p + 3.D0*Z3*p2 + Z7*t + & + 2.0*Z8*tp + Z9*t2 + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + drhodp = (da*tb-ta*db)/b2 + + ! Compressibility: (1/rhof_loc) * drhodp [1/MPa] + compf_mpa = drhodp/rhof_loc + + ! Compressibility [1/Pa] + compf = compf_mpa / pa_conv + + return + end function compf diff --git a/props/bas/compm.f90 b/props/bas/compm.f90 new file mode 100644 index 0000000..977e772 --- /dev/null +++ b/props/bas/compm.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compm returns the compressibility of rock matrix +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility of rock [1/Pa] +!> @details +!> compm returns the compressibility [1/Pa] at node(i,j,k) from the +!> input file.\n + double precision function compm(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_comp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + compm = propunit(uindex(i,j,k),idx_comp,ismpl) + + return + + end function compm diff --git a/props/bas/cpf.f90 b/props/bas/cpf.f90 new file mode 100644 index 0000000..35568f7 --- /dev/null +++ b/props/bas/cpf.f90 @@ -0,0 +1,198 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in J/kg/K) +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return cpf [J/kg/K] +!> @details +!> cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in +!> J/kg/K)\n of pure water, given temperature (t, in C), and +!> pressure (p,in Pa)\n at node(i,j,k).\n \n +!> +!> method: c_p = d/dT E, E= fluid enthalpy.\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> pressures 0.001 - 110 MPa,\n +!> temperature 15 - 350 degC\n + double precision function cpf(i,j,k,ismpl) + use arrays, only: pres, temp + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Enthalpy (J/kg) + double precision :: enth + + ! Derivative of enthalpy wrt T (J/kg/K) + double precision :: denthdt + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.25623465D-3 + double precision, parameter :: Y1 = 0.10184405D-2 + double precision, parameter :: Y2 = 0.22554970D-4 + double precision, parameter :: Y3 = 0.34836663D-7 + double precision, parameter :: Y4 = 0.41769866D-2 + double precision, parameter :: Y5 = -0.21244879D-4 + double precision, parameter :: Y6 = 0.25493516D-7 + double precision, parameter :: Y7 = 0.89557885D-4 + double precision, parameter :: Y8 = 0.10855046D-6 + double precision, parameter :: Y9 = -0.21720560D-6 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+1 + double precision, parameter :: Z1 = 0.23513278D-1 + double precision, parameter :: Z2 = 0.48716386D-4 + double precision, parameter :: Z3 = -0.19935046D-8 + double precision, parameter :: Z4 = -0.50770309D-2 + double precision, parameter :: Z5 = 0.57780287D-5 + double precision, parameter :: Z6 = 0.90972916D-9 + double precision, parameter :: Z7 = -0.58981537D-4 + double precision, parameter :: Z8 = -0.12990752D-7 + double precision, parameter :: Z9 = 0.45872518D-8 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt T + double precision :: da + + ! Derivative of denominator wrt T + double precision :: db + + ! Denominator squared + double precision :: b2 + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Enthalpy + enth = ta/tb + + ! Derivative of numerator + da = Y4 + 2.0d0*Y5*t + 3.0d0*Y6*t2 + Y7*p + & + Y8*p2 + 2.0d0*Y9*tp + + ! Derivative of denominator + db = Z4 + 2.0d0*Z5*t + 3.0d0*Z6*t2 + Z7*p + & + Z8*p2 + 2.0d0*Z9*tp + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + denthdt = da/tb - ta*db/b2 + + ! Isobaric heat capacity (J/kg/K) + cpf = denthdt*1.0d6 + + return + + end function cpf diff --git a/props/bas/disp.f90 b/props/bas/disp.f90 new file mode 100644 index 0000000..36737bf --- /dev/null +++ b/props/bas/disp.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign effective diffusivity z direction to cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return assign effective diffusivity +!> @details +!> assign effective diffusivity, called dispersivity in the input +!> file. + double precision function disp(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_df + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + disp = propunit(uindex(i,j,k),idx_df,ismpl) + + return + + end function disp diff --git a/props/bas/kx.f90 b/props/bas/kx.f90 new file mode 100644 index 0000000..fc22dae --- /dev/null +++ b/props/bas/kx.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in x direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kx returns the permeability in x-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in x-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the x-direction. + double precision function kx(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_kx + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kx = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_kx,ismpl) + + return + + end function kx diff --git a/props/bas/ky.f90 b/props/bas/ky.f90 new file mode 100644 index 0000000..9156b5f --- /dev/null +++ b/props/bas/ky.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in y direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> ky returns the permeability in y-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in y-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the y-direction. + double precision function ky(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_ky + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + ky = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ky,ismpl) + + return + + end function ky diff --git a/props/bas/kz.f90 b/props/bas/kz.f90 new file mode 100644 index 0000000..c72f7b2 --- /dev/null +++ b/props/bas/kz.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in z direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kz returns the permeability in z-direction[m2] at node(i,j,k) from +!> the input file.\n + double precision function kz(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kz = propunit(uindex(i,j,k),idx_kz,ismpl) + + return + + end function kz diff --git a/props/bas/lamf.f90 b/props/bas/lamf.f90 new file mode 100644 index 0000000..ae283bd --- /dev/null +++ b/props/bas/lamf.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the thermal conductivity kf in W/(m*K) of water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity [W/(m*K)] +!> @details +!> Calculate the thermal conductivity kf in W/(m*K) of freshwater, +!> given temperature in degC. Thermal conductivity of freshwater, kfw +!> is calculated using the Phillips (1981) formulation (page 8). \n\n +!> +!> Source:\n\n +!> +!> Phillips, S., Igbene, A., Fair, J., Ozbek, H., & Tavana, M., +!> Technical databook for geothermal energy utilization (1981). +!> http://dx.doi.org/10.2172/6301274 \n\n +!> +!> Range of validity: 20 to 330 degC\n\n +!> +!> temperature tlocal in [C]\n + double precision function lamf(i,j,k,ismpl) + use arrays, only: temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Monomials of temperatures quotient + double precision :: tr, tr2, tr3, tr4 + + ! Coefficients of approximation + double precision, parameter :: c0 = -0.92247d0 + double precision, parameter :: c1 = 2.8395d0 + double precision, parameter :: c2 = 1.8007d0 + double precision, parameter :: c3 = 0.52577d0 + double precision, parameter :: c4 = 0.07344d0 + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Monomials of temperature quotient + tr = (tlocal+273.15d0)/273.15d0 + tr2 = tr*tr + tr3 = tr2*tr + tr4 = tr3*tr + + ! Thermal conductivity [W/(m*K)] + lamf = (c0 + c1*tr - c2*tr2 + c3*tr3 - c4*tr4) + + return + + end function lamf diff --git a/props/bas/lamm.f90 b/props/bas/lamm.f90 new file mode 100644 index 0000000..42ede46 --- /dev/null +++ b/props/bas/lamm.f90 @@ -0,0 +1,128 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate temperature dependent thermal conductivity +!> @param[in] lammref thermal conductivity from input file +!> @param[in] tlocal temperature +!> @param[in] tref reference temperature +!> @param[in] ismpl local sample index +!> @return temperature dependent thermal conductivity +!> @details +!> calculate temperature dependent thermal conductivity\n +!> +!> lam_zoth/haenel = (770degC/(350degC+T) + 0.7) W/mK +!> +!> If T > 800degC, use the formula from zoth & haenel, 1988. \n +!> +!> lamm = lam_zoth/haenel +!> +!> If T < 800degC, use the same formula with a factor `fct` +!> +!> lamm = fct * lam_zoth/haenel +!> +!> The factor `fct` introduces an additional temperature dependence +!> such that\n +!> 1. `lamm(20degC) = lammref`\n +!> 2. `lamm(800degC) = lam_zoth/haenel(800degC)\n\n +!> +!> Thus, the thermal conductivity in the input file should resemble +!> information about the value of the thermal conductivity of the +!> matrix at temperature 20 degC.\n\n +!> +!> Sources: \n +!> Zoth, G., & Haenel, R, Handbook of terrestrial heat-flow density +!> determination, (1988), Appendix 10.1 Thermal +!> Conductivity. http://dx.doi.org/10.1007/978-94-009-2847-3\n\n +!> +!> Lehmann, H., Wang, K., & Clauser, C., Parameter identification and +!> uncertainty analysis for heat transfer at the ktb drill site using +!> a 2-d inverse method, Tectonophysics, 291(1-4), 179–194 +!> (1998). Section 2.2 http://dx.doi.org/10.1016/s0040-1951(98)00039-0 +!> \n + double precision function lamm(lammref,tlocal,tref,ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + ! Thermal conductivity of matrix at tref=20degC + double precision, intent (in) :: lammref + + ! Local temperature [degC] + double precision, intent (in) :: tlocal + + ! Reference temperature [20 degC] + double precision, intent (in) :: tref + + ! Upper limit temperature, where the approximation becomes + ! equal to the general Zoth/Haenel formula + double precision, parameter :: tlimit = 800.0d0 + + ! lam_zoth/haenel at tlocal + double precision :: lamm_zh + + ! lam_zoth/haenel at tref + double precision :: lamm_zhref + + ! Reference Interpolation-factor + double precision :: fctref + + ! Weight: Quotient of temperature differences + double precision :: twgt + + ! Interpolation factor + double precision :: fct + + + if (tlocal > tlimit) then + + ! lam_zoth/haenel at tlocal + lamm = 770.0d0/(350.0d0+tlocal) + 0.7D0 + + else + + ! lam_zoth/haenel at tlocal + lamm_zh = 770.0d0/(350.0d0+tlocal) + 0.7d0 + + ! lam_zoth/haenel at tref + lamm_zhref = 770.0d0/(350.0d0+tref) + 0.7d0 + + ! Reference Interpolation-factor: Input lamm at tref divided + ! by lam_zoth/haenel at tref + fctref = lammref/lamm_zhref + + ! Quotient of temperature differences, local minus reference + ! divided by limit minus reference + twgt = (tlocal-tref)/(tlimit-tref) + + ! Interpolation factor between fctref at tref and 1 at tlimit + fct = fctref*(1-twgt) + twgt + + ! Final lam: input at tref and lam_zoth/haenel at tlimit + lamm = fct*lamm_zh + + end if + + return + + end function lamm diff --git a/props/bas/lx.f90 b/props/bas/lx.f90 new file mode 100644 index 0000000..0850819 --- /dev/null +++ b/props/bas/lx.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lx[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, x-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function lx(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz, idx_an_lx + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_lx,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + lx = lamm(lammref,tlocal,tref,ismpl) + + if (lx<=0.d0 .or. lamfluid<=0.d0) then + write(*,*) 'Error: "lx" computes bad math !', lx, lamfluid, & + tlocal + stop + else + lx = lx**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function lx diff --git a/props/bas/ly.f90 b/props/bas/ly.f90 new file mode 100644 index 0000000..9490b4b --- /dev/null +++ b/props/bas/ly.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity ly[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, y-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function ly(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz, idx_an_ly + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_ly,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + ly = lamm(lammref,tlocal,tref,ismpl) + + if (ly<=0.D0 .or. lamfluid<=0.D0) then + write(*,*) 'Error: "ly" computes bad math !', ly, lamfluid, & + tlocal + stop + else + ly = ly**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function ly diff --git a/props/bas/lz.f90 b/props/bas/lz.f90 new file mode 100644 index 0000000..9aa0714 --- /dev/null +++ b/props/bas/lz.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, z-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function lz(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + lz = lamm(lammref,tlocal,tref,ismpl) + + if (lz<=0.d0 .or. lamfluid<=0.d0) then + write(*,*) 'Error: "lz" computes bad math !', lz, lamfluid, & + tlocal + stop + else + lz = lz**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function lz diff --git a/props/bas/por.f90 b/props/bas/por.f90 new file mode 100644 index 0000000..d4be904 --- /dev/null +++ b/props/bas/por.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign porosity to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return porosity porlocal [-] +!> @details +!> por returns the porosity [-] at node(i,j,k) from the input file.\n + double precision function por(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_por + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + por = propunit(uindex(i,j,k),idx_por,ismpl) + + return + + end function por diff --git a/props/bas/props_check.f90 b/props/bas/props_check.f90 new file mode 100644 index 0000000..af007f3 --- /dev/null +++ b/props/bas/props_check.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current PROPS choice +!> @param[in] ismpl local sample index +!> @details +!> Check the local/current PROPS ldef_props against the PROPS choice +!> in the input file (def_props). + subroutine props_check(ismpl) + use mod_genrlc, only: def_props + + implicit none + + ! Sample index + integer :: ismpl + + ! Local PROPS + character (len=10), parameter :: ldef_props = "bas" + + ! Test options of command line input + logical, external :: test_option + + intrinsic trim + + +#ifndef PROPS_bas + write(*,'(3A)') 'error: this source was written for PROPS=', & + ldef_props, & + ', please correct this check in "props_check.f"!' + stop +#endif + if ( .not. test_option('PROPS='//trim(def_props))) then + if (ldef_props/=def_props) then + write(*,'(7A)') 'Error: model file needs an executable', & + ' build from PROPS=', trim(def_props), & + ', but the current', ' consist of PROPS=', & + trim(ldef_props), '!' + stop + end if + end if + + return + + end subroutine props_check diff --git a/props/bas/props_end.f90 b/props/bas/props_end.f90 new file mode 100644 index 0000000..fc94431 --- /dev/null +++ b/props/bas/props_end.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper finishing property module +!> @param[in] ismpl local sample index +!> @details +!> For bas: Dummy Wrapper. + subroutine props_end(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine props_end diff --git a/props/bas/props_init.f90 b/props/bas/props_init.f90 new file mode 100644 index 0000000..c583244 --- /dev/null +++ b/props/bas/props_init.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper initializing property module +!> @param[in] ismpl local sample index +!> @details +!> Wrapper for calling read_props and check_props. + subroutine props_init(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + CALL read_props(ismpl) + + CALL check_props(ismpl) + + return + + end subroutine props_init diff --git a/props/bas/qc.f90 b/props/bas/qc.f90 new file mode 100644 index 0000000..dc3b9e0 --- /dev/null +++ b/props/bas/qc.f90 @@ -0,0 +1,55 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign transport production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @return transport production +!> @details +!> Assign transport production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> transport production to exist.\n + double precision function qc(i,j,k,spec,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Species index + integer, intent (in) :: spec + + ! Sample index + integer :: ismpl + + ! No transport production + qc = 0.0d0 + + return + + end function qc diff --git a/props/bas/qf.f90 b/props/bas/qf.f90 new file mode 100644 index 0000000..6ed3011 --- /dev/null +++ b/props/bas/qf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign flow production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return flow production +!> @details +!> Assign flow production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> flow production to exist.\n + double precision function qf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + qf = 0.0d0 + + return + + end function qf diff --git a/props/bas/qt.f90 b/props/bas/qt.f90 new file mode 100644 index 0000000..284f102 --- /dev/null +++ b/props/bas/qt.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign heat production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return heat production +!> @details +!> qt returns the heat production [W/m3] at node(i,j,k) from the +!> input file.\n + double precision function qt(i,j,k,ismpl) + + use arrays, only: propunit, uindex, idx_q + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + qt = propunit(uindex(i,j,k),idx_q,ismpl) + + return + + end function qt diff --git a/props/bas/rce.f90 b/props/bas/rce.f90 new file mode 100644 index 0000000..4811222 --- /dev/null +++ b/props/bas/rce.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates volumetric heat capacity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return volumetric heat capacity +!> @details +!> calculates volumetric heat capacity of the system +!> matrix-porosity [J/(K*m3)].\n + double precision function rhoceff(i,j,k,ismpl) + + use arrays, only: temp + ! use mod_temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + double precision, external :: por + + ! Matrix fraction in cell + double precision :: fm + + ! Fluid fraction in cell + double precision :: ff + + ! Heat capacity of the matrix + double precision, external :: rhocm + + ! Heat capacity of the fluid + double precision, external :: rhocf + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local porosity + porlocal = por(i,j,k,ismpl) + + ! Matrix fraction + fm = 1.D0 - porlocal + + ! Fluid fraction + ff = porlocal + + ! Heat capacity in cell, arithmetic mean + rhoceff = ff*rhocf(i,j,k,ismpl) + fm*rhocm(i,j,k,ismpl) + + return + + end function rhoceff diff --git a/props/bas/read_props.f90 b/props/bas/read_props.f90 new file mode 100644 index 0000000..e1a5af4 --- /dev/null +++ b/props/bas/read_props.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read additional user defined parameters +!> @param[in] ismpl local sample index +!> @details +!> For bas: So far no additional user defined parameters. + subroutine read_props(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine read_props diff --git a/props/bas/rhocf.f90 b/props/bas/rhocf.f90 new file mode 100644 index 0000000..ce6d69f --- /dev/null +++ b/props/bas/rhocf.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity times density of water. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> calculates volumetric heat capacity of the fluid [J/(K*m3)].\n + double precision function rhocf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Density of fluid [kg/m3] + double precision :: rfluid + double precision, external :: rhof + + ! Water isobaric head capacity [J/(K*kg)] + double precision :: cfluid + double precision, external :: cpf + + ! water density [kg/m**3] + rfluid = rhof(i,j,k,ismpl) + + ! water isobaric heat capacity [J/(kg*K)] + cfluid = cpf(i,j,k,ismpl) + + ! water volumetric heat capacity [J/(K*m3)] + rhocf = rfluid*cfluid + + return + + end function rhocf diff --git a/props/bas/rhocm.f90 b/props/bas/rhocm.f90 new file mode 100644 index 0000000..68dfbb2 --- /dev/null +++ b/props/bas/rhocm.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of rock. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> temperature tlocal in [C]\n\n +!> +!> Under input file "# rhocm", the temperature variation coefficients +!> cma1, cma2, cma3 can be set. \n +!> Default: cma1 = 1.0d0, cma2 = cma3 = 0.0d0 + double precision function rhocm(i,j,k,ismpl) + use arrays, only: temp, propunit, uindex, idx_rc + use mod_temp, only: cma1, cma2, cma3 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Volumetric heat capacity from input file [J/(kg*m3)] + rhocm = propunit(uindex(i,j,k),idx_rc,ismpl)* & + (cma1+cma2*tlocal+cma3*tlocal*tlocal) + + return + + end function rhocm diff --git a/props/bas/rhof.f90 b/props/bas/rhof.f90 new file mode 100644 index 0000000..0ce5604 --- /dev/null +++ b/props/bas/rhof.f90 @@ -0,0 +1,169 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure water, +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rho [kg/m^3] +!> @details +!> rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure +!> water, given temperature (t, in degC), and pressure (p,in Pa) at +!> node(i,j,k)\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function rhof(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.10000000D+01 + double precision, parameter :: Y1 = 0.17472599D-01 + double precision, parameter :: Y2 = -0.20443098D-04 + double precision, parameter :: Y3 = -0.17442012D-06 + double precision, parameter :: Y4 = 0.49564109D-02 + double precision, parameter :: Y5 = -0.40757664D-04 + double precision, parameter :: Y6 = 0.50676664D-07 + double precision, parameter :: Y7 = 0.50330978D-04 + double precision, parameter :: Y8 = 0.33914814D-06 + double precision, parameter :: Y9 = -0.18383009D-06 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10009476D-02 + double precision, parameter :: Z1 = 0.16812589D-04 + double precision, parameter :: Z2 = -0.24582622D-07 + double precision, parameter :: Z3 = -0.17014984D-09 + double precision, parameter :: Z4 = 0.48841156D-05 + double precision, parameter :: Z5 = -0.32967985D-07 + double precision, parameter :: Z6 = 0.28619380D-10 + double precision, parameter :: Z7 = 0.53249055D-07 + double precision, parameter :: Z8 = 0.30456698D-09 + double precision, parameter :: Z9 = -0.12221899D-09 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Water density + rhof = ta/tb + + return + + end function rhof diff --git a/props/bas/visf.f90 b/props/bas/visf.f90 new file mode 100644 index 0000000..d88452d --- /dev/null +++ b/props/bas/visf.f90 @@ -0,0 +1,167 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return visf [Pa s] +!> @details +!> rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water,\n +!> given temperature (t, in C), and pressure (p,in Pa) at node(i,j,k)\n\n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function visf(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.17409149D-02 + double precision, parameter :: Y1 = 0.18894882D-04 + double precision, parameter :: Y2 = -0.66439332D-07 + double precision, parameter :: Y3 = -0.23122388D-09 + double precision, parameter :: Y4 = -0.31534914D-05 + double precision, parameter :: Y5 = 0.11120716D-07 + double precision, parameter :: Y6 = -0.48576020D-10 + double precision, parameter :: Y7 = 0.28006861D-07 + double precision, parameter :: Y8 = 0.23225035D-09 + double precision, parameter :: Y9 = 0.47180171D-10 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+01 + double precision, parameter :: Z1 = 0.10523153D-01 + double precision, parameter :: Z2 = -0.22658391D-05 + double precision, parameter :: Z3 = -0.31796607D-06 + double precision, parameter :: Z4 = 0.29869141D-01 + double precision, parameter :: Z5 = 0.21844248D-03 + double precision, parameter :: Z6 = -0.87658855D-06 + double precision, parameter :: Z7 = 0.41690362D-03 + double precision, parameter :: Z8 = -0.25147022D-05 + double precision, parameter :: Z9 = 0.22144660D-05 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Viscosity + visf = ta/tb + + return + + end function visf diff --git a/props/basc/check_domain.f90 b/props/basc/check_domain.f90 new file mode 100644 index 0000000..b42ffba --- /dev/null +++ b/props/basc/check_domain.f90 @@ -0,0 +1,188 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief domain of validity for module basc +!> @param[in] ismpl local sample index +!> @details +!> Checking whether pres/temp/(conc) are in domain of props +!> validity. Version for property module basc. \n +!> \n +!> For concentration, an error is thrown and the execution is +!> stopped if the concentration is outside the physical values. + subroutine check_domain(ismpl) + use arrays, only: pres, temp, conc + use mod_genrl, only: i0, j0, k0 + use mod_genrlc, only: def_props + use mod_conc, only: ntrac + use mod_linfos, only: linfos + + implicit none + + ! Sample index + integer :: ismpl + + ! Iteration counters + integer :: i, j, k, l + + ! counters for the values outside domain of validity + ! pres + integer :: icountp + ! temp + integer :: icountt + ! conc + integer :: icountc + + ! min/max boundaries of the domain of validity + ! pres + double precision, parameter :: pmin = 0.01d6 + double precision, parameter :: pmax = 110.0d6 + ! temp + double precision, parameter :: tmin = 0.0d0 + double precision, parameter :: tmax = 350.0d0 + ! conc + double precision, parameter :: cmin = 0.0d0 + double precision, parameter :: cmax = 1.0d5 + ! numerical boundary + double precision, parameter :: csmin = 1.0d-30 + + ! records the overall min/max of values if they are outside + ! domain of validity + double precision :: dpmax, dtmax, dcmax, dhmax + double precision :: dpmin, dtmin, dcmin, dhmin + + intrinsic trim + + + ! Set counters to zero + icountp = 0 + icountt = 0 + icountc = 0 + + ! Set overall min/max to boundaries of the domain of validity + dpmax = pmax + dpmin = pmin + dtmax = tmax + dtmin = tmin + dcmax = cmax + dcmin = cmin + + ! Check pres + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (pres(i,j,k,ismpl)<pmin) then + ! Set min counter + icountp = icountp + 1 + ! Set new overall minimum + dpmin = min(dpmin,pres(i,j,k,ismpl)) + ! Change pres value to minimum of the domain of validity + pres(i,j,k,ismpl) = pmin + end if + if (pres(i,j,k,ismpl)>pmax) then + ! Set max counter + icountp = icountp + 1 + ! Set new overall maximum + dpmax = max(dpmax,pres(i,j,k,ismpl)) + ! Change pres value to maximum of the domain of validity + pres(i,j,k,ismpl) = pmax + end if + end do + end do + end do + + ! Check temp + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (temp(i,j,k,ismpl)<tmin) then + icountt = icountt + 1 + dtmin = min(dtmin,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmin + end if + if (temp(i,j,k,ismpl)>tmax) then + icountt = icountt + 1 + dtmax = max(dtmax,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmax + end if + end do + end do + end do + + ! Check conc + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + do l = 1, ntrac + if (conc(i,j,k,l,ismpl).gt.cmax) then + icountc = icountc +1 + dcmax = max(dcmax, conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmax + end if + if (conc(i,j,k,l,ismpl)<cmin .and. & + conc(i,j,k,l,ismpl)<-csmin) then + icountc = icountc + 1 + dcmin = min(dcmin,conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmin + end if + if (conc(i,j,k,l,ismpl)<csmin) then + ! very small conc values set to zero to avoid + ! numerically instabilities + conc(i,j,k,l,ismpl) = cmin + end if + end do + end do + end do + end do + +! disable the warning output for linfos(3)==-1 + if (linfos(3)>=0) then + if (icountp/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: pres not in domain of validity of module <', & + trim(def_props), '> at ', icountp, ' points (min', dpmin, & + ', max', dpmax, ')!' + if (icountt/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: temp not in domain of validity of module <', & + trim(def_props), '> at ', icountt, ' points (min', dtmin, & + ', max', dtmax, ')!' + if (icountc/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: conc not in domain of validity of module <', & + trim(def_props), '> at ', icountc, ' points (min', dcmin, & + ', max', dcmax, ')!' + + ! error outputs for hard physical concentration boundaries + if (dcmax > cmax) then + write(unit = *, fmt = *) "[E1] Error in check_domain.f90:", & + " maximum concentration dcmax= ", dcmax, & + " larger than allowed maximum value cmax=", cmax + stop + end if + if (dcmin > cmin) then + write(unit = *, fmt = *) "[E2] Error in check_domain.f90:", & + " minimum concentration dcmin= ", dcmin, & + " smaller than allowed minimum value cmin=", cmin + stop + end if + end if + + return + + end subroutine check_domain diff --git a/props/basc/compf.f90 b/props/basc/compf.f90 new file mode 100644 index 0000000..affec5e --- /dev/null +++ b/props/basc/compf.f90 @@ -0,0 +1,195 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compf(i,j,k,ismpl) calculates the compressibility of the fluid +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compf [1 / Pa] +!> @details +!> compf(i,j,k,ismpl) calculates the compressibility in (in 1/Pa) of +!> salin water, given temperature (t, in c) pressure (p,in pa), and +!> salinity (s, in mol/L) at node(i,j,k)\n\n +!> +!> Sources:\n +!> Driesner & Heinrich, The system H2O-NaCl. Part I: Correlation +!> formulae for phase relations in temperature-pressure-composition +!> space from 0 to 1000 C, 0 to 5000 bar, and 0 to 1 XNaCl +!> Geochimica et Cosmochimica Acta 71 (2007) 4880-4901\n\n +!> +!> Driesner, The system H2O-NaCl. Part II: Correlations for molar +!> volume, enthalpy, and isobaric heat capacity from 0 to 1000 C, 1 +!> to 5000 bar, and 0 to 1 XNaCl Geochimica et Cosmochimica Acta 71 +!> (2007) 4902-4919\n\n + double precision function compf(i,j,k,ismpl) + use arrays, only: temp, pres, tsal + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Molar mass of NaCl [g/mol] + double precision, parameter :: mmnacl = 58.44277d0 + + ! Mass fraction of NaCl in solution [-] + double precision :: fracnacl + + ! Molar mass of water, H2O [g/mol] + double precision, parameter :: mmwater = 18.01528d0 + + ! Temperature, [degC] + double precision :: t + + ! Pressure [MPa] + double precision :: p + + ! Monomials of pressure [bar] + double precision :: pb, pb2, pb3 + + ! Pure water compressibility [1/Pa] + double precision cw + double precision, external :: compw + + ! Pure water density [kg/m3] + double precision rw + double precision, external :: rhow + + ! Local salinity [mol/kg] + double precision :: s + + ! Mole fraction of NaCl [-] + double precision :: xnacl + + ! Temperature at which pure water has the same molar volume + ! as the solution [K] + double precision :: tv + + ! Driesner2007: Coefficients + + ! Equation (9) + double precision :: n1, n10, n11, n12 + + ! Equation (10) + double precision :: n2, n20, n21, n22, n23 + + ! Equation (11), (12) + double precision :: n1x, n2x + + ! Table 4 + double precision :: n30, n300, n301, n302 + double precision :: n31, n310, n311, n312 + + ! Deviation function (13) + double precision :: dt + + + ! Local temperature [degC] + t = temp(i,j,k,ismpl) + + ! Local pressure [MPa] + p = pres(i,j,k,ismpl)*pa_conv1 + + ! Local salinity [mol/L] + s = tsal(i,j,k,ismpl) + + ! pure water compressibility [1 / Pa] + cw = compw(p,t) + + if (s<=0.0d0) then + + compf = cw + + else + ! pure water density [g/L = kg/m3] + rw = rhow(p,t) + + ! Pressure [bar] and pressure monomials + pb = p*10.0d0 + pb2 = pb*pb + pb3 = pb*pb2 + + ! Mass fraction of NaCl, mol/L > (g/L) / (g/L) mass fraction + fracnacl = s*mmnacl/(rw+s*mmnacl) + + ! Mole fraction of NaCl, (mol/L) / (mol/L) + xnacl = (fracnacl/mmnacl) / (fracnacl/mmnacl+(1-fracnacl)/mmwater) + + ! Driesner2007 parameters, Table 4 + n11 = -54.2958d0 - 45.7623d0*exp(-9.44785d-4*pb) + n21 = -2.6142d0 - 0.000239092d0*pb + n22 = 0.0356828d0 + 4.37235d-6*pb + 2.0566d-9*pb2 + n300 = 7.60664d6 / (pb+472.051d0)**2 + n301 = -50.0d0 - 86.1446d0*exp(-6.21128d-4*pb) + n302 = 294.318d0 * exp(-5.66735d-3*pb) + n310 = -0.0732761d0 * exp(-2.3772d-3*pb) - 5.2948d-5*pb + n311 = -47.2747d0 + 24.3653d0*exp(-1.25533D-3*pb) + n312 = -0.278529 - 0.00081381*pb + + ! Driesner2007: n1 and n2 parameters for liquid NaCl + n1x = 330.47d0 + 0.942876d0*sqrt(pb) + 0.0817193*pb - & + 2.47556D-8*pb2 + 3.45052D-10*pb3 + n2x = -0.0370751 + 0.00237723*sqrt(pb) + 5.42049D-5*pb + & + 5.84709D-9*pb2 - 5.99373D-13*pb3 + + ! Driesner2007: Set xnacl=1 in (9), => n1 = n1x + n10 = n1x + + ! Driesner2007: Set xnacl=0 in (9) => n1 = 0.0d0 + n12 = -n10 - n11 + + ! Driesner2007: Set xnacl=0 in (10) => n2 = 1.0d0 + n20 = 1.0d0 - n21*sqrt(n22) + + ! Driesner2007: Set xnacl=1 in (10) => n2 = n2x + n23 = n2x - n20 - n21*sqrt(1.0d0+n22) + + ! Driesner2007: Equation (9) + n1 = n10 + n11*(1.0d0-xnacl) + n12*(1.0d0-xnacl)**2 + + ! Driesner2007: Equation (10) + n2 = n20 + n21*sqrt(xnacl+n22) + n23*xnacl + + ! Driesner2007: deviation function D(T) Equations (14)-(16) + n30 = n300 * (exp(n301*xnacl) - 1.0d0) + n302 * xnacl + n31 = n310 * exp(n311*xnacl) + n312 * xnacl + dt = n30 * exp(n31 * t) + + ! Temperature at which pure water has the same molar volume + ! as the solution + tv = n1 + n2*t+dt + + ! Pure water compressibility at tv + compf = compw(p,tv) + + end if + + return + + end function compf diff --git a/props/basc/compm.f90 b/props/basc/compm.f90 new file mode 100644 index 0000000..977e772 --- /dev/null +++ b/props/basc/compm.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compm returns the compressibility of rock matrix +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility of rock [1/Pa] +!> @details +!> compm returns the compressibility [1/Pa] at node(i,j,k) from the +!> input file.\n + double precision function compm(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_comp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + compm = propunit(uindex(i,j,k),idx_comp,ismpl) + + return + + end function compm diff --git a/props/basc/compw.f90 b/props/basc/compw.f90 new file mode 100644 index 0000000..da71bc6 --- /dev/null +++ b/props/basc/compw.f90 @@ -0,0 +1,180 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compw calculates compressibility of pure water +!> @param[in] p_h pressure [MPa] +!> @param[in] t_h temperature [degC] +!> @return compressibility compw [1./Pa] +!> @details +!> compw calculates compressibility of pure water [1/Pa] +!> given temperature (t, in C), and pressure (p,in MPa) +!> at pressure/temperature (p_h,t).\n \n +!> +!> Method: \n +!> +!> compw = 1/rhow d/dP rhow, \n +!> +!> where rhow= water density.\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n \n +!> +!> input:\n +!> pressure p [MPa]\n +!> temperature t in [degC]\n + double precision function compw(p_h,t_h) + use mod_flow, only: pa_conv + + implicit none + + ! Input Pressure (MPa) + DOUBLE PRECISION p_h + + ! Input temperature (degc) + DOUBLE PRECISION t_h + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.10000000D+01 + double precision, parameter :: Y1 = 0.17472599D-01 + double precision, parameter :: Y2 = -0.20443098D-04 + double precision, parameter :: Y3 = -0.17442012D-06 + double precision, parameter :: Y4 = 0.49564109D-02 + double precision, parameter :: Y5 = -0.40757664D-04 + double precision, parameter :: Y6 = 0.50676664D-07 + double precision, parameter :: Y7 = 0.50330978D-04 + double precision, parameter :: Y8 = 0.33914814D-06 + double precision, parameter :: Y9 = -0.18383009D-06 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10009476D-02 + double precision, parameter :: Z1 = 0.16812589D-04 + double precision, parameter :: Z2 = -0.24582622D-07 + double precision, parameter :: Z3 = -0.17014984D-09 + double precision, parameter :: Z4 = 0.48841156D-05 + double precision, parameter :: Z5 = -0.32967985D-07 + double precision, parameter :: Z6 = 0.28619380D-10 + double precision, parameter :: Z7 = 0.53249055D-07 + double precision, parameter :: Z8 = 0.30456698D-09 + double precision, parameter :: Z9 = -0.12221899D-09 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt P + double precision :: da + + ! Derivative of denominator wrt P + double precision :: db + + ! Denominator squared + double precision :: b2 + + ! Water density (local) + double precision :: rhow_loc + + ! Derivative of water density wrt P + double precision :: drhodp + + ! Compressibiliy in Mpa + double precision :: compw_mpa + + + ! pressure [MPa] + p = p_h + + ! temperature [degC] + t = t_h + + ! Compute monomials in pressure and temperature + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + t2p = t2*p + tp2 = t*p2 + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Water density + rhow_loc = ta/tb + + ! Derivative of numerator + da = Y1 + 2.D0*Y2*p + 3.D0*Y3*p2 + Y7*t + & + 2.D0*Y8*tp + Y9*t2 + + ! Derivative of denominator + db = Z1 + 2.D0*Z2*p + 3.D0*Z3*p2 + Z7*t + & + 2.0*Z8*tp + Z9*t2 + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + drhodp = (da*tb-ta*db)/b2 + + ! Compressibility: (1/rhow_loc) * drhodp [1/MPa] + compw_mpa = drhodp/rhow_loc + + ! Compressibility [1/Pa] + compw = compw_mpa / pa_conv + + + return + + end function compw diff --git a/props/basc/cpf.f90 b/props/basc/cpf.f90 new file mode 100644 index 0000000..790830b --- /dev/null +++ b/props/basc/cpf.f90 @@ -0,0 +1,176 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief cpf(i,j,k,ismpl) calculates the isobaric heat capacity of the fluid [J/kg/K] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return cpf [J/kg/K] +!> @details +!> cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in +!> J/kg/K) of brine, given temperature (t, in degC) pressure (p,in MPa), +!> and salinity (s, in mol/L) at node(i,j,k)\\n \n +!> +!> Source:\n +!> Driesner & Heinrich, The system H2O-NaCl. Part I: Correlation +!> formulae for phase relations in temperature-pressure-composition +!> space from 0 to 1000 C, 0 to 5000 bar, and 0 to 1 XNaCl +!> Geochimica et Cosmochimica Acta 71 (2007) 4880-4901\n\n +!> +!> Driesner, The system H2O-NaCl. Part II: Correlations for molar +!> volume, enthalpy, and isobaric heat capacity from 0 to 1000 C, 1 +!> to 5000 bar, and 0 to 1 XNaCl Geochimica et Cosmochimica Acta 71 +!> (2007) 4902-4919\n \n + double precision function cpf(i,j,k,ismpl) + use arrays, only: temp, pres, tsal + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local Temperature, [degC] + double precision :: t + + ! Local Pressure [MPa] + double precision :: p + + ! Local salinity [mol/kg] + double precision :: s + + ! Monomials of pressure [bar] + double precision :: pb, pb2 + + ! Pure water compressibility [1/Pa] + double precision cw + double precision, external :: compw + + ! Pure water density [kg/m3] + double precision rw + double precision, external :: rhow + + ! Pure water thermal conductivity [J/kg/K] + double precision, external :: cpw + + ! Molar mass of NaCl [g/mol] + double precision, parameter :: mmnacl = 58.44277d0 + + ! Mass fraction of NaCl in solution [-] + double precision :: fracnacl + + ! Molar mass of water, H2O [g/mol] + double precision, parameter :: mmwater = 18.01528d0 + + ! Mole fraction of NaCl [-] + double precision :: xnacl + + ! Temperature at which pure water has the same specific + ! enthalpy as the solution [K] + double precision :: tv + + ! Driesner2007: Coefficients + + ! Equation (23) + double precision :: q1, q10, q11, q12 + + ! Equation (24) + double precision :: q2, q20, q21, q22, q23 + + ! Equation (25), (26) + double precision :: q1x, q2x + + + ! Local temperature [degC] + t = temp(i,j,k,ismpl) + + ! Local pressure [MPa] + p = pres(i,j,k,ismpl)*pa_conv1 + + ! Local salinity [mol/L] + s = tsal(i,j,k,ismpl) + + if (s<=0.0d0) then + + ! Pure water heat capacity + cpf = cpw(p,t) + + else + + ! pure water density [g/L = kg/m3] + rw = rhow(p,t) + + ! Pressure monomials [bar] + pb = p*10.0d0 + pb2 = pb*pb + + ! Mass fraction of NaCl, mol/L > (g/L) / (g/L) mass fraction + fracnacl = s*mmnacl/(rw+s*mmnacl) + + ! Mole fraction of NaCl, (mol/L) / (mol/L) + xnacl = (fracnacl/mmnacl) / (fracnacl/mmnacl+(1-fracnacl)/mmwater) + + ! Driesner2007 parameters, Table 5 + q11 = -32.1724d0 + 0.0621255d0*pb + q21 = -1.69513d0 - 4.52781d-4*pb - 6.04279d-8*pb2 + q22 = 0.0612567d0 + 1.88082d-5*pb + + ! Driesner2007: q1 and q2 parameters for liquid NaCl + q1x = 47.9048d0 - 9.36994d-3*pb + 6.51059d-6*pb2 + q2x = 0.241022d0 + 3.45087d-5*pb - 4.28356d-9*pb2 + + ! Driesner2007: Set xnacl=1 in (23) => q1 = q1x + q10 = q1x + + ! Driesner2007: Set xnacl=0 in (23) => q1 = 0.0d0 + q12 = -q10 - q11 + + ! Driesner2007: Set xnacl=0 in (24) => q2 = 1.0d0 + q20 = 1.0d0 - q21*sqrt(q22) + + ! Driesner2007: Set xnacl=1 in (10) => q2 = q2x + q23 = q2x - q20 - q21*sqrt(1.0d0+q22) + + ! Driesner2007: Equation (23) + q1 = q10 + q11*(1.0d0-xnacl) + q12*(1.0d0-xnacl)**2 + + ! Driesner2007: Equation (24) + q2 = q20 + q21*sqrt(xnacl+q22) + q23*xnacl + + ! Temperature at which pure water has the same specific + ! enthalpy as the solution + tv = q1 + q2*t + + ! Isobaric heat capacity of solution + cpf = q2*cpw(p,tv) + + end if + + return + + end function cpf diff --git a/props/basc/cpw.f90 b/props/basc/cpw.f90 new file mode 100644 index 0000000..d15d38b --- /dev/null +++ b/props/basc/cpw.f90 @@ -0,0 +1,179 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief cpf(i,j,k,ismpl) calculates the isobaric heat capacity of water in (in J/kg/K) +!> @param[in] p pressure [MPa] +!> @param[in] t temperature [degC] +!> @return cpf [J/kg/K] +!> @details +!> cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in +!> J/kg/K)\n of pure water, given temperature (t, in C), and +!> pressure (p,in Pa)\n at node(i,j,k).\n \n +!> +!> method: c_p = d/dT E, E= fluid enthalpy.\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> pressures 0.001 - 110 MPa,\n +!> temperature 15 - 350 degC\n + double precision function cpw(p,t) + + implicit none + + ! Input Pressure (MPa) + double precision, intent (in) :: p + + ! Input Temperature (degC) + double precision, intent (in) :: t + + ! Enthalpy (J/kg) + double precision :: enth + + ! Derivative of enthalpy wrt T (J/kg/K) + double precision :: denthdt + + ! Monomials of temperature and pressure + double precision :: t2, t3 + double precision :: p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.25623465D-3 + double precision, parameter :: Y1 = 0.10184405D-2 + double precision, parameter :: Y2 = 0.22554970D-4 + double precision, parameter :: Y3 = 0.34836663D-7 + double precision, parameter :: Y4 = 0.41769866D-2 + double precision, parameter :: Y5 = -0.21244879D-4 + double precision, parameter :: Y6 = 0.25493516D-7 + double precision, parameter :: Y7 = 0.89557885D-4 + double precision, parameter :: Y8 = 0.10855046D-6 + double precision, parameter :: Y9 = -0.21720560D-6 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+1 + double precision, parameter :: Z1 = 0.23513278D-1 + double precision, parameter :: Z2 = 0.48716386D-4 + double precision, parameter :: Z3 = -0.19935046D-8 + double precision, parameter :: Z4 = -0.50770309D-2 + double precision, parameter :: Z5 = 0.57780287D-5 + double precision, parameter :: Z6 = 0.90972916D-9 + double precision, parameter :: Z7 = -0.58981537D-4 + double precision, parameter :: Z8 = -0.12990752D-7 + double precision, parameter :: Z9 = 0.45872518D-8 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt T + double precision :: da + + ! Derivative of denominator wrt T + double precision :: db + + ! Denominator squared + double precision :: b2 + + + ! Temperature out of bounds + if (t > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + t,") out of bounds (> 360 degC)." + stop + end if + if (t < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + t,") out of bounds (< 0 degC)." + stop + end if + + ! Pressure out of bounds + if (p > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + p,") out of bounds (> 110 MPa)" + stop + end if + if (p < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + p,") out of bounds (< 0.001 MPa)" + stop + end if + + ! Compute monomials in pressure and temperature + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Enthalpy + enth = ta/tb + + ! Derivative of numerator + da = Y4 + 2.0d0*Y5*t + 3.0d0*Y6*t2 + Y7*p + & + Y8*p2 + 2.0d0*Y9*tp + + ! Derivative of denominator + db = Z4 + 2.0d0*Z5*t + 3.0d0*Z6*t2 + Z7*p + & + Z8*p2 + 2.0d0*Z9*tp + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + denthdt = da/tb - ta*db/b2 + + ! Isobaric heat capacity (J/kg/K) + cpw = denthdt*1.0d6 + + + return + + end function cpw diff --git a/props/basc/disp.f90 b/props/basc/disp.f90 new file mode 100644 index 0000000..36737bf --- /dev/null +++ b/props/basc/disp.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign effective diffusivity z direction to cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return assign effective diffusivity +!> @details +!> assign effective diffusivity, called dispersivity in the input +!> file. + double precision function disp(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_df + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + disp = propunit(uindex(i,j,k),idx_df,ismpl) + + return + + end function disp diff --git a/props/basc/kx.f90 b/props/basc/kx.f90 new file mode 100644 index 0000000..fc22dae --- /dev/null +++ b/props/basc/kx.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in x direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kx returns the permeability in x-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in x-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the x-direction. + double precision function kx(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_kx + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kx = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_kx,ismpl) + + return + + end function kx diff --git a/props/basc/ky.f90 b/props/basc/ky.f90 new file mode 100644 index 0000000..9156b5f --- /dev/null +++ b/props/basc/ky.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in y direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> ky returns the permeability in y-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in y-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the y-direction. + double precision function ky(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_ky + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + ky = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ky,ismpl) + + return + + end function ky diff --git a/props/basc/kz.f90 b/props/basc/kz.f90 new file mode 100644 index 0000000..c72f7b2 --- /dev/null +++ b/props/basc/kz.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in z direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kz returns the permeability in z-direction[m2] at node(i,j,k) from +!> the input file.\n + double precision function kz(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kz = propunit(uindex(i,j,k),idx_kz,ismpl) + + return + + end function kz diff --git a/props/basc/lamf.f90 b/props/basc/lamf.f90 new file mode 100644 index 0000000..d22e47c --- /dev/null +++ b/props/basc/lamf.f90 @@ -0,0 +1,123 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the thermal conductivity kf of fluid [W/(m*K)] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lamf[W/(m*K)] +!> @details +!> calculate the thermal conductivity kf in W/(m*K) of saline water, +!> given temperature in degC, and salinity in mass fraction (g/g)of +!> NaCl. Thermal conductivity of freshwater, kfw is calculated using +!> the Phillips (1981) formulation (page8). \n \n +!> +!> C = S./(1 + S)*1.d2;C2=C.*C; % C=salinity in mol/kg \n\n +!> kf = kfw.*(1.d0 - (2.3434d-3 - 7.924d-6*T + 3.924d-8*T2).*C ... \n +!> + (1.06d-5 - 2.d-8*T - 1.2d-10*T2).*C2) \n\n +!> Source:\n\n +!> +!> Phillips, S., Igbene, A., Fair, J., Ozbek, H., & Tavana, M., +!> Technical databook for geothermal energy utilization (1981). +!> http://dx.doi.org/10.2172/6301274 \n\n +!> +!> Range of validity: 20 to 330degC and up to 4 molal NaCl\n\n +!> input:\n +!> pressure p [MPa]\n +!> temperature t in [C]\n +!> salinity s in [mol/L]\n + double precision function lamf(i,j,k,ismpl) + use arrays, only: pres, temp, tsal + use mod_flow, only: pa_conv1 + IMPLICIT NONE + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local Temperature (degC) + double precision :: t + + ! Local Pressure (MPa) + double precision :: p + + ! Local salinity [mol/kg / mol/L] + double precision :: s + + ! Monomials of temperature + double precision :: t2, t3, t4 + + ! Salinity from Phillips1981 [-] + double precision :: sr + + ! Monomial of salinity from Phillips1981 [-] + double precision :: sr2 + + ! Factor for thermal conductivity, Phillips1981 (2) + double precision :: lamfac + + ! Pure water thermal conductivity [W/(m*K)] + double precision, external :: lamw + + + ! Local pressure [MPa] + p = pres(i,j,k,ismpl)*pa_conv1 + + ! Local temperature [degC] + t = temp(i,j,k,ismpl) + + ! Local salinity [mol/L / mol/kg] + s = tsal(i,j,k,ismpl) + + if (s<=0.0d0) then + + ! Pure water conductivity + lamf = lamw(p,t) + + else + + ! Salinity according to Phillips (1981) between (2) and (3) + sr =5844.3d0*s/(1.0d3+58.443d0*s) + + ! Monomials in salinity and temperature + sr2 = sr*sr + t2 = t*t + t3 = t2*t + t4 = t3*t + + ! Factor lamf/lamw from Phillips1981, eq (2) + lamfac = 1.0d0 - (2.3434d-3 - 7.924d-6*t + 3.924d-8*t2) * sr + & + (1.06d-5 - 2.0d-8*t + 1.2d-10*t2) * sr2 + + ! Thermal conductivity of fluid + lamf = lamfac*lamw(p,t) + + end if + + return + + end function lamf diff --git a/props/basc/lamm.f90 b/props/basc/lamm.f90 new file mode 100644 index 0000000..42ede46 --- /dev/null +++ b/props/basc/lamm.f90 @@ -0,0 +1,128 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate temperature dependent thermal conductivity +!> @param[in] lammref thermal conductivity from input file +!> @param[in] tlocal temperature +!> @param[in] tref reference temperature +!> @param[in] ismpl local sample index +!> @return temperature dependent thermal conductivity +!> @details +!> calculate temperature dependent thermal conductivity\n +!> +!> lam_zoth/haenel = (770degC/(350degC+T) + 0.7) W/mK +!> +!> If T > 800degC, use the formula from zoth & haenel, 1988. \n +!> +!> lamm = lam_zoth/haenel +!> +!> If T < 800degC, use the same formula with a factor `fct` +!> +!> lamm = fct * lam_zoth/haenel +!> +!> The factor `fct` introduces an additional temperature dependence +!> such that\n +!> 1. `lamm(20degC) = lammref`\n +!> 2. `lamm(800degC) = lam_zoth/haenel(800degC)\n\n +!> +!> Thus, the thermal conductivity in the input file should resemble +!> information about the value of the thermal conductivity of the +!> matrix at temperature 20 degC.\n\n +!> +!> Sources: \n +!> Zoth, G., & Haenel, R, Handbook of terrestrial heat-flow density +!> determination, (1988), Appendix 10.1 Thermal +!> Conductivity. http://dx.doi.org/10.1007/978-94-009-2847-3\n\n +!> +!> Lehmann, H., Wang, K., & Clauser, C., Parameter identification and +!> uncertainty analysis for heat transfer at the ktb drill site using +!> a 2-d inverse method, Tectonophysics, 291(1-4), 179–194 +!> (1998). Section 2.2 http://dx.doi.org/10.1016/s0040-1951(98)00039-0 +!> \n + double precision function lamm(lammref,tlocal,tref,ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + ! Thermal conductivity of matrix at tref=20degC + double precision, intent (in) :: lammref + + ! Local temperature [degC] + double precision, intent (in) :: tlocal + + ! Reference temperature [20 degC] + double precision, intent (in) :: tref + + ! Upper limit temperature, where the approximation becomes + ! equal to the general Zoth/Haenel formula + double precision, parameter :: tlimit = 800.0d0 + + ! lam_zoth/haenel at tlocal + double precision :: lamm_zh + + ! lam_zoth/haenel at tref + double precision :: lamm_zhref + + ! Reference Interpolation-factor + double precision :: fctref + + ! Weight: Quotient of temperature differences + double precision :: twgt + + ! Interpolation factor + double precision :: fct + + + if (tlocal > tlimit) then + + ! lam_zoth/haenel at tlocal + lamm = 770.0d0/(350.0d0+tlocal) + 0.7D0 + + else + + ! lam_zoth/haenel at tlocal + lamm_zh = 770.0d0/(350.0d0+tlocal) + 0.7d0 + + ! lam_zoth/haenel at tref + lamm_zhref = 770.0d0/(350.0d0+tref) + 0.7d0 + + ! Reference Interpolation-factor: Input lamm at tref divided + ! by lam_zoth/haenel at tref + fctref = lammref/lamm_zhref + + ! Quotient of temperature differences, local minus reference + ! divided by limit minus reference + twgt = (tlocal-tref)/(tlimit-tref) + + ! Interpolation factor between fctref at tref and 1 at tlimit + fct = fctref*(1-twgt) + twgt + + ! Final lam: input at tref and lam_zoth/haenel at tlimit + lamm = fct*lamm_zh + + end if + + return + + end function lamm diff --git a/props/basc/lamw.f90 b/props/basc/lamw.f90 new file mode 100644 index 0000000..e7c96ef --- /dev/null +++ b/props/basc/lamw.f90 @@ -0,0 +1,77 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the thermal conductivity kf in W/(m*K) of water +!> @param[in] p cell pressure [MPa] +!> @param[in] t temperature [degC] +!> @return thermal conductivity [W/(m*K)] +!> @details +!> Calculate the thermal conductivity kf in W/(m*K) of freshwater, +!> given temperature in degC. Thermal conductivity of freshwater, kfw +!> is calculated using the Phillips (1981) formulation (page 8). \n\n +!> +!> Source:\n\n +!> +!> Phillips, S., Igbene, A., Fair, J., Ozbek, H., & Tavana, M., +!> Technical databook for geothermal energy utilization (1981). +!> http://dx.doi.org/10.2172/6301274 \n\n +!> +!> Range of validity: 20 to 330 degC\n\n +!> +!> temperature tlocal in [C]\n + double precision function lamw(p,t) + use arrays, only: temp + + implicit none + + ! Pressure p [MPa] + double precision, intent (in) :: p + + ! Temperature t [degC] + double precision, intent (in) :: t + + ! Temperature (degC) + double precision :: tlocal + + ! Monomials of temperatures quotient + double precision :: tr, tr2, tr3, tr4 + + ! Coefficients of approximation + double precision, parameter :: c0 = -0.92247d0 + double precision, parameter :: c1 = 2.8395d0 + double precision, parameter :: c2 = 1.8007d0 + double precision, parameter :: c3 = 0.52577d0 + double precision, parameter :: c4 = 0.07344d0 + + + ! Monomials of temperature quotient + tr = (t+273.15d0) / 273.15d0 + tr2 = tr*tr + tr3 = tr2*tr + tr4 = tr3*tr + + ! Thermal conductivity [W/(m*K)] + lamw = (c0 + c1*tr - c2*tr2 + c3*tr3 - c4*tr4) + + return + + end function lamw diff --git a/props/basc/lx.f90 b/props/basc/lx.f90 new file mode 100644 index 0000000..0850819 --- /dev/null +++ b/props/basc/lx.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lx[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, x-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function lx(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz, idx_an_lx + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_lx,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + lx = lamm(lammref,tlocal,tref,ismpl) + + if (lx<=0.d0 .or. lamfluid<=0.d0) then + write(*,*) 'Error: "lx" computes bad math !', lx, lamfluid, & + tlocal + stop + else + lx = lx**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function lx diff --git a/props/basc/ly.f90 b/props/basc/ly.f90 new file mode 100644 index 0000000..9490b4b --- /dev/null +++ b/props/basc/ly.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity ly[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, y-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function ly(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz, idx_an_ly + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_ly,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + ly = lamm(lammref,tlocal,tref,ismpl) + + if (ly<=0.D0 .or. lamfluid<=0.D0) then + write(*,*) 'Error: "ly" computes bad math !', ly, lamfluid, & + tlocal + stop + else + ly = ly**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function ly diff --git a/props/basc/lz.f90 b/props/basc/lz.f90 new file mode 100644 index 0000000..9aa0714 --- /dev/null +++ b/props/basc/lz.f90 @@ -0,0 +1,98 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity, z-direction.\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> temperature tlocal in [degC]\n + double precision function lz(i,j,k,ismpl) + use arrays, only: temp, uindex, propunit, idx_por, idx_lz + use mod_temp, only: tref + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local uindex + integer :: ui + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + + ! Reference matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Local matrix thermal conductivity [W/(m*K)] + double precision, external :: lamm + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Local unit index + ui = uindex(i,j,k) + + ! Local porosity + porlocal = propunit(ui,idx_por,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(ui,idx_lz,ismpl) + + ! Local matrix thermal conductivity [W/(m*K)] + lz = lamm(lammref,tlocal,tref,ismpl) + + if (lz<=0.d0 .or. lamfluid<=0.d0) then + write(*,*) 'Error: "lz" computes bad math !', lz, lamfluid, & + tlocal + stop + else + lz = lz**(1.d0-porlocal)*lamfluid**porlocal + end if + + return + + end function lz diff --git a/props/basc/por.f90 b/props/basc/por.f90 new file mode 100644 index 0000000..d4be904 --- /dev/null +++ b/props/basc/por.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign porosity to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return porosity porlocal [-] +!> @details +!> por returns the porosity [-] at node(i,j,k) from the input file.\n + double precision function por(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_por + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + por = propunit(uindex(i,j,k),idx_por,ismpl) + + return + + end function por diff --git a/props/basc/props_check.f90 b/props/basc/props_check.f90 new file mode 100644 index 0000000..846d353 --- /dev/null +++ b/props/basc/props_check.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current PROPS choice +!> @param[in] ismpl local sample index +!> @details +!> Check the local/current PROPS ldef_props against the PROPS choice +!> in the input file (def_props). + subroutine props_check(ismpl) + use mod_genrlc, only: def_props + + implicit none + + ! Sample index + integer :: ismpl + + ! Local PROPS + character (len=10), parameter :: ldef_props = "basc" + + ! Test options of command line input + logical, external :: test_option + + intrinsic trim + + +#ifndef PROPS_basc + write(*,'(3A)') 'error: this source was written for PROPS=', & + ldef_props, & + ', please correct this check in "props_check.f"!' + stop +#endif + if ( .not. test_option('PROPS='//trim(def_props))) then + if (ldef_props/=def_props) then + write(*,'(7A)') 'Error: model file needs an executable', & + ' build from PROPS=', trim(def_props), & + ', but the current', ' consist of PROPS=', & + trim(ldef_props), '!' + stop + end if + end if + + return + + end subroutine props_check diff --git a/props/basc/props_end.f90 b/props/basc/props_end.f90 new file mode 100644 index 0000000..fc94431 --- /dev/null +++ b/props/basc/props_end.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper finishing property module +!> @param[in] ismpl local sample index +!> @details +!> For bas: Dummy Wrapper. + subroutine props_end(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine props_end diff --git a/props/basc/props_init.f90 b/props/basc/props_init.f90 new file mode 100644 index 0000000..c583244 --- /dev/null +++ b/props/basc/props_init.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper initializing property module +!> @param[in] ismpl local sample index +!> @details +!> Wrapper for calling read_props and check_props. + subroutine props_init(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + CALL read_props(ismpl) + + CALL check_props(ismpl) + + return + + end subroutine props_init diff --git a/props/basc/qc.f90 b/props/basc/qc.f90 new file mode 100644 index 0000000..dc3b9e0 --- /dev/null +++ b/props/basc/qc.f90 @@ -0,0 +1,55 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign transport production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @return transport production +!> @details +!> Assign transport production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> transport production to exist.\n + double precision function qc(i,j,k,spec,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Species index + integer, intent (in) :: spec + + ! Sample index + integer :: ismpl + + ! No transport production + qc = 0.0d0 + + return + + end function qc diff --git a/props/basc/qf.f90 b/props/basc/qf.f90 new file mode 100644 index 0000000..6ed3011 --- /dev/null +++ b/props/basc/qf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign flow production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return flow production +!> @details +!> Assign flow production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> flow production to exist.\n + double precision function qf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + qf = 0.0d0 + + return + + end function qf diff --git a/props/basc/qt.f90 b/props/basc/qt.f90 new file mode 100644 index 0000000..284f102 --- /dev/null +++ b/props/basc/qt.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign heat production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return heat production +!> @details +!> qt returns the heat production [W/m3] at node(i,j,k) from the +!> input file.\n + double precision function qt(i,j,k,ismpl) + + use arrays, only: propunit, uindex, idx_q + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + qt = propunit(uindex(i,j,k),idx_q,ismpl) + + return + + end function qt diff --git a/props/basc/rce.f90 b/props/basc/rce.f90 new file mode 100644 index 0000000..4811222 --- /dev/null +++ b/props/basc/rce.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates volumetric heat capacity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return volumetric heat capacity +!> @details +!> calculates volumetric heat capacity of the system +!> matrix-porosity [J/(K*m3)].\n + double precision function rhoceff(i,j,k,ismpl) + + use arrays, only: temp + ! use mod_temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + double precision, external :: por + + ! Matrix fraction in cell + double precision :: fm + + ! Fluid fraction in cell + double precision :: ff + + ! Heat capacity of the matrix + double precision, external :: rhocm + + ! Heat capacity of the fluid + double precision, external :: rhocf + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local porosity + porlocal = por(i,j,k,ismpl) + + ! Matrix fraction + fm = 1.D0 - porlocal + + ! Fluid fraction + ff = porlocal + + ! Heat capacity in cell, arithmetic mean + rhoceff = ff*rhocf(i,j,k,ismpl) + fm*rhocm(i,j,k,ismpl) + + return + + end function rhoceff diff --git a/props/basc/read_props.f90 b/props/basc/read_props.f90 new file mode 100644 index 0000000..e1a5af4 --- /dev/null +++ b/props/basc/read_props.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read additional user defined parameters +!> @param[in] ismpl local sample index +!> @details +!> For bas: So far no additional user defined parameters. + subroutine read_props(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine read_props diff --git a/props/basc/rhocf.f90 b/props/basc/rhocf.f90 new file mode 100644 index 0000000..ce6d69f --- /dev/null +++ b/props/basc/rhocf.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity times density of water. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> calculates volumetric heat capacity of the fluid [J/(K*m3)].\n + double precision function rhocf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Density of fluid [kg/m3] + double precision :: rfluid + double precision, external :: rhof + + ! Water isobaric head capacity [J/(K*kg)] + double precision :: cfluid + double precision, external :: cpf + + ! water density [kg/m**3] + rfluid = rhof(i,j,k,ismpl) + + ! water isobaric heat capacity [J/(kg*K)] + cfluid = cpf(i,j,k,ismpl) + + ! water volumetric heat capacity [J/(K*m3)] + rhocf = rfluid*cfluid + + return + + end function rhocf diff --git a/props/basc/rhocm.f90 b/props/basc/rhocm.f90 new file mode 100644 index 0000000..68dfbb2 --- /dev/null +++ b/props/basc/rhocm.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of rock. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> temperature tlocal in [C]\n\n +!> +!> Under input file "# rhocm", the temperature variation coefficients +!> cma1, cma2, cma3 can be set. \n +!> Default: cma1 = 1.0d0, cma2 = cma3 = 0.0d0 + double precision function rhocm(i,j,k,ismpl) + use arrays, only: temp, propunit, uindex, idx_rc + use mod_temp, only: cma1, cma2, cma3 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Volumetric heat capacity from input file [J/(kg*m3)] + rhocm = propunit(uindex(i,j,k),idx_rc,ismpl)* & + (cma1+cma2*tlocal+cma3*tlocal*tlocal) + + return + + end function rhocm diff --git a/props/basc/rhof.f90 b/props/basc/rhof.f90 new file mode 100644 index 0000000..6761b3a --- /dev/null +++ b/props/basc/rhof.f90 @@ -0,0 +1,127 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the density of the fluid (in kg/m^3), +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rho [kg/m^3] +!> @details +!> rhow(i,j,k,ismpl) calculates the density in (in kg/m^3) of brine, +!> given temperature (t, in c) pressure (p,in pa), and salinity (s, in +!> mol/L) at node(i,j,k)\n +!> +!> Source:\n +!> Batzle, M., & Wang, Z., Seismic properties of pore fluids, +!> GEOPHYSICS, 57(11), 1396–1408 (1992). +!> http://dx.doi.org/10.1190/1.1443207 \n\n +!> +!> Pressures 5-100 MPa, Temperature 20-350°C, Salinity <=320 g/L\n \n +!> +!> CODE VERIFICATION:\n +!> INPUT: TEMP = 298.15K P =0.1013 MPa S = 0.25 g/g OUTPUT: RHO = 1187.35 kg/m3\n +!> INPUT: TEMP = 393.15K P = 30 MPa S = 0.10 g/g OUTPUT: RHO = 1027.06 kg/m3\n\n +!> +!> ARGUMENTS NAME TYPE UNITS DESCRIPTION\n +!> INPUT: Temp Real T C Temperature \n +!> Real P Pa Pressure\n +!> Real S g/g Salinity in mass fraction\n +!> OUTPUT: LABEL RHO Real kg/m3 Density of brine \n + double precision function rhof(i,j,k,ismpl) + use arrays, only: temp, pres, tsal + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: t + + ! Pressure (MPa) + double precision :: p + + ! Salinity (mol/L) + double precision :: s + + ! Salinity fraction (g/L) + double precision :: sr + + ! Molar mass of NaCl [g/mol] + ! double precision, parameter :: mmnacl = 58.44277d0 + double precision, parameter :: mmnacl = 58.44d0 + + ! Pure water density (kg/m3) + double precision :: rw + double precision, external :: rhow + + ! Pure water density (g/cm3) + double precision :: rw_gcm3 + + ! Fluid density (g/cm3) + double precision :: rhof_gcm3 + + + ! Local Temperature (degC) + t = temp(i,j,k,ismpl) + + ! Local Pressure [MPa] + p = pres(i,j,k,ismpl)*pa_conv1 + + ! Local salinity [mol/L] + s = tsal(i,j,k,ismpl) + + ! Pure water density [kg/m3] + rw = rhow(p,t) + + + if (s<=0.0d0) then + + rhof = rw + + else + + ! mol/L (Molarity) > g/g (Mass fraCtion) + sr = s*mmnacl/(rw+s*mmnacl) + + ! Pure water density [g/cm3] + rw_gcm3 = rw / 1.0d3 + + ! Batzle, Equation (27b), densities in g/cm3 + rhof_gcm3 = rw_gcm3 + sr*(0.668d0 + 0.44d0*sr & + + 1.0D-6*(3.0d2*p - 2.4d3*p*sr & + + t * (80.0d0 + 3.0d0*t - 3.3d3*sr - 13.0d0*p + 47.0d0*p*sr))) + + ! Fluid density [kg/m3] + rhof = rhof_gcm3 * 1.0d3 + end if + + return + + end function rhof diff --git a/props/basc/rhow.f90 b/props/basc/rhow.f90 new file mode 100644 index 0000000..8a70911 --- /dev/null +++ b/props/basc/rhow.f90 @@ -0,0 +1,105 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhow calculates the density of pure water [kg/m3] +!> @param[in] p pressure [MPa] +!> @param[in] t temperature [degC] +!> @return rhow density of pure water [kg/m3] +!> @details +!> rhow(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure +!> water, given temperature (t, in degC), and pressure (p,in Pa)\n \n +!> +!> Source: \n +!> +!> Magri, F. (2005), Mechanismus und Fluiddynamik der +!> Salzwasserzirkulation im Norddeutschen Becken: Ergebnisse +!> thermohaliner numerischer Simulationen, Doktorarbeit, +!> Geoforschungszentrum Potsdam \n \n +!> +!> Specifically: Equation (2.12) and Table 2-1 + double precision function rhow(p,t) + + implicit none + + ! Local temperature (degC) + double precision, intent (in) :: t + + ! Local pressure (MPa) + double precision, intent (in) :: p + + ! Pressure in kPa + double precision :: pk + + ! Monomials in pressure and temperature + double precision :: pk2, t2, t4, t6 + + ! Coefficients from Magri2005 Equation (2.12) + double precision a, b, c, d, e, f, g + + ! Coefficients from Magri2005 Table 2-1 + double precision, parameter :: a0 = 9.99792877961606D02 + double precision, parameter :: a1 = 5.07605113140940D-04 + double precision, parameter :: a2 = -5.28425478164183D-10 + double precision, parameter :: b0 = 5.13864847162196D-02 + double precision, parameter :: b1 = -3.61991396354483D-06 + double precision, parameter :: b2 = 7.97204102509724D-12 + double precision, parameter :: c0 = -7.53557031774437D-03 + double precision, parameter :: c1 = 6.32712093275576D-08 + double precision, parameter :: c2 = -1.66203631393248D-13 + double precision, parameter :: d0 = 4.60380647957350D-05 + double precision, parameter :: d1 = -5.61299059722121D-10 + double precision, parameter :: d2 = 1.80924436489400D-15 + double precision, parameter :: e0 = -2.26651454175013D-07 + double precision, parameter :: e1 = 3.36874416675978D-12 + double precision, parameter :: e2 = -1.30352149261326D-17 + double precision, parameter :: f0 = 6.14889851856743D-10 + double precision, parameter :: f1 = -1.06165223196756D-14 + double precision, parameter :: f2 = 4.75014903737416D-20 + double precision, parameter :: g0 = -7.39221950969522D-13 + double precision, parameter :: g1 = 1.42790422913922D-17 + double precision, parameter :: g2 = -7.13130230531541D-23 + + + ! Unit [kPa] is needed after Magri(2005); the forwarded p is in [MPa] + pk = p*1000 + + ! Monomials in pressure and temperature + pk2 = pk*pk + t2 = t*t + t4 = t2*t2 + t6 = t4*t2 + + ! Coefficients from Magri2005, Equation (2.12) + a = a0 + a1*pk + a2*pk2 + b = b0 + b1*pk + b2*pk2 + c = c0 + c1*pk + c2*pk2 + d = d0 + d1*pk + d2*pk2 + e = e0 + e1*pk + e2*pk2 + f = f0 + f1*pk + f2*pk2 + g = g0 + g1*pk + g2*pk2 + + ! Water density [kg/m3] + rhow = a + b*t + c*t2 + d*t2*t + e*t4 + f*t4*t + g*t6 + + return + + end function rhow diff --git a/props/basc/visf.f90 b/props/basc/visf.f90 new file mode 100644 index 0000000..5706195 --- /dev/null +++ b/props/basc/visf.f90 @@ -0,0 +1,112 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates viscosity of aqueous NaCl solutions +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return visc +!> @details +!> Source:\n +!> Batzle, M., & Wang, Z., Seismic properties of pore fluids, +!> GEOPHYSICS, 57(11), 1396–1408 (1992). +!> http://dx.doi.org/10.1190/1.1443207 \n\n +!>\n +!> Pressures 5-100 MPa, Temperature 20-350°C, Salinity <=320 g/L\n +!>\n + double precision function visf(i,j,k,ismpl) + use arrays, only: pres, temp, tsal + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: t + + ! Pressure (MPa) + double precision :: p + + ! Salinity (mol/L) + double precision :: s + + ! Mass fraction [-] + double precision :: sr + + ! Pure water density (kg/m3) + double precision :: rw + double precision, external :: rhow + + ! Pure water viscosity [Pa s] + double precision, external :: visw + + ! Molar mass of NaCl [g/mol] + ! double precision, parameter :: mmnacl = 58.44277d0 + double precision, parameter :: mmnacl = 58.44d0 + + ! Viscosity [cP] + double precision :: visf_cp + + + ! Pressure [MPa] + p = pres(i,j,k,ismpl)*pa_conv1 + + ! Temperature [degC] + t = temp(i,j,k,ismpl) + + ! Salinity [mol/L] + s = tsal(i,j,k,ismpl) + + + if (s <= 0.D0) then + + visf = visw(p,t) + + else + + ! Pure water density [kg/m3] + rw = rhow(p,t) + + ! mol/L (Molarity) > [g/L] = [kg/m3; ]g/g (mass fraction) + sr = s*mmnacl/(rw+s*mmnacl) + + ! Viscosity formula after Batzle & Wang [cP] + visf_cp = 0.1d0 + 0.333d0 * sr & + + (1.65d0 + 91.9d0 * sr**3) * & + exp(-(0.42d0 * (sr**(0.8d0) - 0.17d0)**2 + 0.045d0) * t**(0.8d0)) + + ! Conversion of viscosity from [cP] to [Pa s] + visf = visf_cp * 1.0d-3 + + end if + + return + + end function visf diff --git a/props/basc/visw.f90 b/props/basc/visw.f90 new file mode 100644 index 0000000..da0d321 --- /dev/null +++ b/props/basc/visw.f90 @@ -0,0 +1,124 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water +!> @param[in] p cell pressure [MPa] +!> @param[in] t temperature [degC] +!> @return visw [Pa s] +!> @details +!> rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water,\n +!> given temperature (t, in C), and pressure (p,in Pa) at node(i,j,k)\n\n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function visw(p,t) + + implicit none + + ! Temperature (degC) + double precision, intent (in) :: t + + ! Pressure (MPa) + double precision, intent (in) :: p + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.17409149D-02 + double precision, parameter :: Y1 = 0.18894882D-04 + double precision, parameter :: Y2 = -0.66439332D-07 + double precision, parameter :: Y3 = -0.23122388D-09 + double precision, parameter :: Y4 = -0.31534914D-05 + double precision, parameter :: Y5 = 0.11120716D-07 + double precision, parameter :: Y6 = -0.48576020D-10 + double precision, parameter :: Y7 = 0.28006861D-07 + double precision, parameter :: Y8 = 0.23225035D-09 + double precision, parameter :: Y9 = 0.47180171D-10 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+01 + double precision, parameter :: Z1 = 0.10523153D-01 + double precision, parameter :: Z2 = -0.22658391D-05 + double precision, parameter :: Z3 = -0.31796607D-06 + double precision, parameter :: Z4 = 0.29869141D-01 + double precision, parameter :: Z5 = 0.21844248D-03 + double precision, parameter :: Z6 = -0.87658855D-06 + double precision, parameter :: Z7 = 0.41690362D-03 + double precision, parameter :: Z8 = -0.25147022D-05 + double precision, parameter :: Z9 = 0.22144660D-05 + + ! Monomials of temperature and pressure + double precision :: t2, t3 + double precision :: p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + + ! Compute monomials in pressure and temperature + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Viscosity + visw = ta/tb + + return + + end function visw diff --git a/props/const/check_domain.f90 b/props/const/check_domain.f90 new file mode 100644 index 0000000..8a7fceb --- /dev/null +++ b/props/const/check_domain.f90 @@ -0,0 +1,188 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief domain of validity for module const +!> @param[in] ismpl local sample index +!> @details +!> Checking whether pres/temp/(conc) are in domain of props +!> validity. Version for property module const. \n +!> \n +!> For concentration, an error is thrown and the execution is +!> stopped if the concentration is outside the physical values. + subroutine check_domain(ismpl) + use arrays, only: pres, temp, conc + use mod_genrl, only: i0, j0, k0 + use mod_genrlc, only: def_props + use mod_conc, only: ntrac + use mod_linfos, only: linfos + + implicit none + + ! Sample index + integer :: ismpl + + ! Iteration counters + integer :: i, j, k, l + + ! counters for the values outside domain of validity + ! pres + integer :: icountp + ! temp + integer :: icountt + ! conc + integer :: icountc + + ! min/max boundaries of the domain of validity + ! pres + double precision, parameter :: pmin = 0.01d6 + double precision, parameter :: pmax = 110.0d6 + ! temp + double precision, parameter :: tmin = 0.0d0 + double precision, parameter :: tmax = 350.0d0 + ! conc + double precision, parameter :: cmin = 0.0d0 + double precision, parameter :: cmax = 1.0d5 + ! numerical boundary + double precision, parameter :: csmin = 1.0d-30 + + ! records the overall min/max of values if they are outside + ! domain of validity + double precision :: dpmax, dtmax, dcmax, dhmax + double precision :: dpmin, dtmin, dcmin, dhmin + + intrinsic trim + + + ! Set counters to zero + icountp = 0 + icountt = 0 + icountc = 0 + + ! Set overall min/max to boundaries of the domain of validity + dpmax = pmax + dpmin = pmin + dtmax = tmax + dtmin = tmin + dcmax = cmax + dcmin = cmin + + ! Check pres + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (pres(i,j,k,ismpl)<pmin) then + ! Set min counter + icountp = icountp + 1 + ! Set new overall minimum + dpmin = min(dpmin,pres(i,j,k,ismpl)) + ! Change pres value to minimum of the domain of validity + pres(i,j,k,ismpl) = pmin + end if + if (pres(i,j,k,ismpl)>pmax) then + ! Set max counter + icountp = icountp + 1 + ! Set new overall maximum + dpmax = max(dpmax,pres(i,j,k,ismpl)) + ! Change pres value to maximum of the domain of validity + pres(i,j,k,ismpl) = pmax + end if + end do + end do + end do + + ! Check temp + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (temp(i,j,k,ismpl)<tmin) then + icountt = icountt + 1 + dtmin = min(dtmin,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmin + end if + if (temp(i,j,k,ismpl)>tmax) then + icountt = icountt + 1 + dtmax = max(dtmax,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmax + end if + end do + end do + end do + + ! Check conc + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + do l = 1, ntrac + if (conc(i,j,k,l,ismpl).gt.cmax) then + icountc = icountc +1 + dcmax = max(dcmax, conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmax + end if + if (conc(i,j,k,l,ismpl)<cmin .and. & + conc(i,j,k,l,ismpl)<-csmin) then + icountc = icountc + 1 + dcmin = min(dcmin,conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmin + end if + if (conc(i,j,k,l,ismpl)<csmin) then + ! very small conc values set to zero to avoid + ! numerically instabilities + conc(i,j,k,l,ismpl) = cmin + end if + end do + end do + end do + end do + +! disable the warning output for linfos(3)==-1 + if (linfos(3)>=0) then + if (icountp/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: pres not in domain of validity of module <', & + trim(def_props), '> at ', icountp, ' points (min', dpmin, & + ', max', dpmax, ')!' + if (icountt/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: temp not in domain of validity of module <', & + trim(def_props), '> at ', icountt, ' points (min', dtmin, & + ', max', dtmax, ')!' + if (icountc/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: conc not in domain of validity of module <', & + trim(def_props), '> at ', icountc, ' points (min', dcmin, & + ', max', dcmax, ')!' + + ! error outputs for hard physical concentration boundaries + if (dcmax > cmax) then + write(unit = *, fmt = *) "[E1] Error in check_domain.f90:", & + " maximum concentration dcmax= ", dcmax, & + " larger than allowed maximum value cmax=", cmax + stop + end if + if (dcmin > cmin) then + write(unit = *, fmt = *) "[E2] Error in check_domain.f90:", & + " minimum concentration dcmin= ", dcmin, & + " smaller than allowed minimum value cmin=", cmin + stop + end if + end if + + return + + end subroutine check_domain diff --git a/props/const/compf.f90 b/props/const/compf.f90 new file mode 100644 index 0000000..aa53366 --- /dev/null +++ b/props/const/compf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates compressibility of the fluid +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compf[Pa s] +!> @details +!> compf returns the compressibility of the fluid [1/Pa] at node(i,j,k) +!> from the input file.\n + double precision function compf(i,j,k,ismpl) + use mod_const, only: fprops, pconst_compf + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + compf = fprops(pconst_compf) + + return + + end function compf diff --git a/props/const/compm.f90 b/props/const/compm.f90 new file mode 100644 index 0000000..c5c6962 --- /dev/null +++ b/props/const/compm.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compm calculates compressibility of rock +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @details +!> compm returns compressibility of rock at node(i,j,k) from the input +!> file.\n + double precision function compm(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_comp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + compm = propunit(uindex(i,j,k),idx_comp,ismpl) + + return + + end function compm diff --git a/props/const/cpf.f90 b/props/const/cpf.f90 new file mode 100644 index 0000000..54ae96c --- /dev/null +++ b/props/const/cpf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates isobaric heat capacity of the fluid +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return cpf[Pa s] +!> @details +!> input:\n +!> cpf returns isobaric heat capacity of the fluid from the input file.\n + double precision function cpf(i,j,k,ismpl) + use mod_const, only: fprops, pconst_cpf + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + cpf = fprops(pconst_cpf) + + return + + end function cpf diff --git a/props/const/disp.f90 b/props/const/disp.f90 new file mode 100644 index 0000000..36737bf --- /dev/null +++ b/props/const/disp.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign effective diffusivity z direction to cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return assign effective diffusivity +!> @details +!> assign effective diffusivity, called dispersivity in the input +!> file. + double precision function disp(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_df + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + disp = propunit(uindex(i,j,k),idx_df,ismpl) + + return + + end function disp diff --git a/props/const/kx.f90 b/props/const/kx.f90 new file mode 100644 index 0000000..fc22dae --- /dev/null +++ b/props/const/kx.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in x direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kx returns the permeability in x-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in x-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the x-direction. + double precision function kx(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_kx + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kx = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_kx,ismpl) + + return + + end function kx diff --git a/props/const/ky.f90 b/props/const/ky.f90 new file mode 100644 index 0000000..9156b5f --- /dev/null +++ b/props/const/ky.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in y direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> ky returns the permeability in y-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in y-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the y-direction. + double precision function ky(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_ky + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + ky = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ky,ismpl) + + return + + end function ky diff --git a/props/const/kz.f90 b/props/const/kz.f90 new file mode 100644 index 0000000..c72f7b2 --- /dev/null +++ b/props/const/kz.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in z direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kz returns the permeability in z-direction[m2] at node(i,j,k) from +!> the input file.\n + double precision function kz(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kz = propunit(uindex(i,j,k),idx_kz,ismpl) + + return + + end function kz diff --git a/props/const/lamf.f90 b/props/const/lamf.f90 new file mode 100644 index 0000000..92f3270 --- /dev/null +++ b/props/const/lamf.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns thermal conductivity of the fluid. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lamf[W/(m*K)] +!> @details +!> lamf returns the thermal conductivity of the fluid [W/(m*K)] at +!> node(i,j,k) from the input file.\n + double precision function lamf(i,j,k,ismpl) + use mod_const, only: fprops, pconst_lamf + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + lamf = fprops(pconst_lamf) + + return + + end function lamf diff --git a/props/const/lx.f90 b/props/const/lx.f90 new file mode 100644 index 0000000..417668d --- /dev/null +++ b/props/const/lx.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lx[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity .\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> thermal conductivity of fluid lamf [W/(m*K)]\n +!> thermal conductivity of matrix lammref [W/(m*K)]\n + double precision function lx(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_lz, idx_an_lx + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local porosity [-] + double precision, external :: por + + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(uindex(i,j,k),idx_lz,ismpl)* & + propunit(uindex(i,j,k),idx_an_lx,ismpl) + + lx = lammref**(1.0d0-por(i,j,k,ismpl))*lamfluid**por(i,j,k,ismpl) + + return + + end function lx diff --git a/props/const/ly.f90 b/props/const/ly.f90 new file mode 100644 index 0000000..b293f7b --- /dev/null +++ b/props/const/ly.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity ly[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity .\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> thermal conductivity of fluid lamf [W/(m*K)]\n +!> thermal conductivity of matrix lammref [W/(m*K)]\n + double precision function ly(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_lz, idx_an_ly + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local porosity [-] + double precision, external :: por + + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(uindex(i,j,k),idx_lz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ly,ismpl) + + ly = lammref**(1.0d0-por(i,j,k,ismpl))*lamfluid**por(i,j,k,ismpl) + + return + + end function ly diff --git a/props/const/lz.f90 b/props/const/lz.f90 new file mode 100644 index 0000000..128b614 --- /dev/null +++ b/props/const/lz.f90 @@ -0,0 +1,71 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase system +!> matrix-porosity .\n\n +!> +!> input:\n +!> porosity porlocal [-]\n +!> thermal conductivity of fluid lamf [W/(m*K)]\n +!> thermal conductivity of matrix lammref [W/(m*K)]\n + double precision function lz(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_lz + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local fluid thermal conductivity [W/(m*K)] + double precision :: lamfluid + double precision, external :: lamf + + ! Matrix thermal conductivity [W/(m*K)] + double precision :: lammref + + ! Local porosity [-] + double precision, external :: por + + + ! Local fluid thermal conductivity [W/(m*K)] + lamfluid = lamf(i,j,k,ismpl) + + ! Reference matrix thermal conductivity [W/(m*K)] + lammref = propunit(uindex(i,j,k),idx_lz,ismpl) + + lz = lammref**(1.0d0-por(i,j,k,ismpl))*lamfluid**por(i,j,k,ismpl) + + return + + end function lz diff --git a/props/const/mod_const.f90 b/props/const/mod_const.f90 new file mode 100644 index 0000000..00b339c --- /dev/null +++ b/props/const/mod_const.f90 @@ -0,0 +1,64 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief global variables and constants for PROPS=const. +module mod_const + + !> @brief Dimension of fluid property index array. + !> @details + !> Dimension of fluid property index array. \n + !> Dimension of fluid property index array fprops. + integer, parameter :: npropsf = 5 + + !> @brief Index of rhof in fluid property index array. + !> @details + !> Index of rhof in fluid property index array. \n + integer, parameter :: pconst_rhof = 1 + + !> @brief Index of compf in fluid property index array. + !> @details + !> Index of compf in fluid property index array. \n + integer, parameter :: pconst_compf = 2 + + !> @brief Index of cpf in fluid property index array. + !> @details + !> Index of cpf in fluid property index array. \n + integer, parameter :: pconst_cpf = 3 + + !> @brief Index of lamf in fluid property index array. + !> @details + !> Index of lamf in fluid property index array. \n + integer, parameter :: pconst_lamf = 4 + + !> @brief Index of visf in fluid property index array. + !> @details + !> Index of visf in fluid property index array. \n + integer, parameter :: pconst_visf = 5 + + !> @brief Fluid property index array. + !> @details + !> Fluid property index array. \n + !> The array contains indices for parameters rhof, compf, cpf, lamf, + !> visf. + double precision, dimension (npropsf) :: fprops + +end module mod_const diff --git a/props/const/por.f90 b/props/const/por.f90 new file mode 100644 index 0000000..d4be904 --- /dev/null +++ b/props/const/por.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign porosity to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return porosity porlocal [-] +!> @details +!> por returns the porosity [-] at node(i,j,k) from the input file.\n + double precision function por(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_por + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + por = propunit(uindex(i,j,k),idx_por,ismpl) + + return + + end function por diff --git a/props/const/props_check.f90 b/props/const/props_check.f90 new file mode 100644 index 0000000..12553ad --- /dev/null +++ b/props/const/props_check.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current PROPS choice +!> @param[in] ismpl local sample index +!> @details +!> Check the local/current PROPS ldef_props against the PROPS choice +!> in the input file (def_props). + subroutine props_check(ismpl) + use mod_genrlc, only: def_props + + implicit none + + ! Sample index + integer :: ismpl + + ! Local PROPS + character (len=10), parameter :: ldef_props = 'const' + + ! Test options of command line input + logical, external :: test_option + + intrinsic trim + + +#ifndef PROPS_const + write(*,'(3A)') 'error: this source was written for PROPS=', & + ldef_props, & + ', please correct this check in "props_check.f"!' + stop +#endif + if ( .not. test_option('PROPS='//trim(def_props))) then + if (ldef_props/=def_props) then + write(*,'(7A)') 'Error: model file needs an executable', & + ' build from PROPS=', trim(def_props), & + ', but the current', ' consist of PROPS=', & + trim(ldef_props), '!' + stop + end if + end if + + return + + end subroutine props_check diff --git a/props/const/props_end.f90 b/props/const/props_end.f90 new file mode 100644 index 0000000..5368656 --- /dev/null +++ b/props/const/props_end.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper finishing property module +!> @param[in] ismpl local sample index +!> @details +!> For const: Dummy Wrapper. + subroutine props_end(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine props_end diff --git a/props/const/props_init.f90 b/props/const/props_init.f90 new file mode 100644 index 0000000..c583244 --- /dev/null +++ b/props/const/props_init.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper initializing property module +!> @param[in] ismpl local sample index +!> @details +!> Wrapper for calling read_props and check_props. + subroutine props_init(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + CALL read_props(ismpl) + + CALL check_props(ismpl) + + return + + end subroutine props_init diff --git a/props/const/qc.f90 b/props/const/qc.f90 new file mode 100644 index 0000000..dc3b9e0 --- /dev/null +++ b/props/const/qc.f90 @@ -0,0 +1,55 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign transport production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @return transport production +!> @details +!> Assign transport production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> transport production to exist.\n + double precision function qc(i,j,k,spec,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Species index + integer, intent (in) :: spec + + ! Sample index + integer :: ismpl + + ! No transport production + qc = 0.0d0 + + return + + end function qc diff --git a/props/const/qf.f90 b/props/const/qf.f90 new file mode 100644 index 0000000..6ed3011 --- /dev/null +++ b/props/const/qf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign flow production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return flow production +!> @details +!> Assign flow production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> flow production to exist.\n + double precision function qf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + qf = 0.0d0 + + return + + end function qf diff --git a/props/const/qt.f90 b/props/const/qt.f90 new file mode 100644 index 0000000..284f102 --- /dev/null +++ b/props/const/qt.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign heat production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return heat production +!> @details +!> qt returns the heat production [W/m3] at node(i,j,k) from the +!> input file.\n + double precision function qt(i,j,k,ismpl) + + use arrays, only: propunit, uindex, idx_q + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + qt = propunit(uindex(i,j,k),idx_q,ismpl) + + return + + end function qt diff --git a/props/const/rce.f90 b/props/const/rce.f90 new file mode 100644 index 0000000..4811222 --- /dev/null +++ b/props/const/rce.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates volumetric heat capacity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return volumetric heat capacity +!> @details +!> calculates volumetric heat capacity of the system +!> matrix-porosity [J/(K*m3)].\n + double precision function rhoceff(i,j,k,ismpl) + + use arrays, only: temp + ! use mod_temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + double precision, external :: por + + ! Matrix fraction in cell + double precision :: fm + + ! Fluid fraction in cell + double precision :: ff + + ! Heat capacity of the matrix + double precision, external :: rhocm + + ! Heat capacity of the fluid + double precision, external :: rhocf + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local porosity + porlocal = por(i,j,k,ismpl) + + ! Matrix fraction + fm = 1.D0 - porlocal + + ! Fluid fraction + ff = porlocal + + ! Heat capacity in cell, arithmetic mean + rhoceff = ff*rhocf(i,j,k,ismpl) + fm*rhocm(i,j,k,ismpl) + + return + + end function rhoceff diff --git a/props/const/read_props.f90 b/props/const/read_props.f90 new file mode 100644 index 0000000..206ba6c --- /dev/null +++ b/props/const/read_props.f90 @@ -0,0 +1,116 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read user defined additionally parameter +!> @param[in] ismpl local sample index + subroutine read_props(ismpl) + use arrays + use mod_flow, only: rref + use mod_genrl + use mod_genrlc, only: project + use mod_const, only: npropsf, fprops, pconst_rhof, & + pconst_compf, pconst_cpf, pconst_lamf, pconst_visf + use mod_linfos, only: linfos + + implicit none + + ! Sample index + integer :: ismpl + + ! Filename of input file + character (len=80) :: filename + + ! String of curretly read line from input file + character (len=80) :: line + + ! Index + integer :: i + + ! String utilities + integer, external :: lblank + logical, external :: found + + ! External input utility + logical, external :: no_ext_link + + + ! Set filename + filename = project(:lblank(project)) + write(*,*) ' ' + write(*,*) ' reading constant fluid properties:' + write(*,*) ' from file "', filename, '"' + write(*,*) ' ' + + ! open project config file + open(79,file=filename,status='old') + + ! input from keyword '# fluid props' + if (found(79,key_char//' fluid props',line,.false.)) then + read(79,*) (fprops(i),i=1,npropsf) + + if (linfos(3)>=1) then + write(*,*) ' [R] : constant fluid properties' + write(*,*) ' ' + write(*,'(a,/a,a)') ' fluid properties: ', & + ' rhof compf cpf lamf', & + ' visf' + write(*,'(6e12.4)') (fprops(i),i=1,npropsf) + write(*,*) ' ' + end if + + else + + ! default fluid density + fprops(pconst_rhof) = 998.0d0 + ! default fluid compressibility + fprops(pconst_compf) = 5.0d-8 + ! default fluid volumetric heat capacity (rho*c) + fprops(pconst_cpf) = 4218.0d0 + ! default fluid thermal conductivity + fprops(pconst_lamf) = 0.65d0 + ! default fluid viscosity + fprops(pconst_visf) = 1.0d-3 + + write(*,*) ' [D] : constant fluid properties assumed' + write(*,*) ' ' + + if (linfos(3)>=1) then + write(*,'(a,/a,a)') ' fluid properties: ', & + ' rhof compf cpf lamf', & + ' visf' + write(*,'(6e12.4)') (fprops(i),i=1,npropsf) + write(*,*) ' ' + end if + + end if + + ! Overwriting rref with the constant density read in this file + write(*,*) ' [?] : WARNING: overwrite "rref" with constant "rhof"' + rref = fprops(pconst_rhof) + + + ! close project config file + close(79) + + return + + end subroutine read_props diff --git a/props/const/rhocf.f90 b/props/const/rhocf.f90 new file mode 100644 index 0000000..92060b2 --- /dev/null +++ b/props/const/rhocf.f90 @@ -0,0 +1,47 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of the fluid. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhocf rc[W/(m*K)] + double precision function rhocf(i,j,k,ismpl) + use mod_const, only: fprops, pconst_cpf, pconst_rhof + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + rhocf = fprops(pconst_cpf)*fprops(pconst_rhof) + + return + + end function rhocf diff --git a/props/const/rhocm.f90 b/props/const/rhocm.f90 new file mode 100644 index 0000000..e674ce8 --- /dev/null +++ b/props/const/rhocm.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of rock +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return heat capacity*density = volumetric heat capacity rhocm [J/(K*m3)] +!> @details +!> rhocm returns the volumetric heat capacity [J/(K*m3)] at +!> node(i,j,k) from the input file.\n + double precision function rhocm(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_rc + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + rhocm = propunit(uindex(i,j,k),idx_rc,ismpl) + + return + + end function rhocm diff --git a/props/const/rhof.f90 b/props/const/rhof.f90 new file mode 100644 index 0000000..8a699ec --- /dev/null +++ b/props/const/rhof.f90 @@ -0,0 +1,51 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates density of the fluid +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rho [kg/m^3] +!> @details +!> input:\n +!> rhof returns the density of the fluid [kg/m3] at node(i,j,k) from the +!> input file.\n + double precision function rhof(i,j,k,ismpl) + use mod_const, only: fprops, pconst_rhof + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + rhof = fprops(pconst_rhof) + + return + + end function rhof diff --git a/props/const/visf.f90 b/props/const/visf.f90 new file mode 100644 index 0000000..13ea3f9 --- /dev/null +++ b/props/const/visf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief returns viscosity of the fluid +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return visf[Pa s] +!> @details +!> visf returns the viscosity of the fluid [Pa s] at node(i,j,k) from the +!> input file.\n\n + double precision function visf(i,j,k,ismpl) + use mod_const, only: fprops, pconst_visf + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + visf = fprops(pconst_visf) + + return + + end function visf diff --git a/props/ghe/check_domain.f90 b/props/ghe/check_domain.f90 new file mode 100644 index 0000000..03181e3 --- /dev/null +++ b/props/ghe/check_domain.f90 @@ -0,0 +1,188 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief domain of validity for module ghe +!> @param[in] ismpl local sample index +!> @details +!> Checking whether pres/temp/(conc) are in domain of props +!> validity. Version for property module ghe. \n +!> \n +!> For concentration, an error is thrown and the execution is +!> stopped if the concentration is outside the physical values. + subroutine check_domain(ismpl) + use arrays, only: pres, temp, conc + use mod_genrl, only: i0, j0, k0 + use mod_genrlc, only: def_props + use mod_conc, only: ntrac + use mod_linfos, only: linfos + + implicit none + + ! Sample index + integer :: ismpl + + ! Iteration counters + integer :: i, j, k, l + + ! counters for the values outside domain of validity + ! pres + integer :: icountp + ! temp + integer :: icountt + ! conc + integer :: icountc + + ! min/max boundaries of the domain of validity + ! pres + double precision, parameter :: pmin = 0.01d6 + double precision, parameter :: pmax = 110.0d6 + ! temp + double precision, parameter :: tmin = 0.0d0 + double precision, parameter :: tmax = 350.0d0 + ! conc + double precision, parameter :: cmin = 0.0d0 + double precision, parameter :: cmax = 1.0d5 + ! numerical boundary + double precision, parameter :: csmin = 1.0d-22 + + ! records the overall min/max of values if they are outside + ! domain of validity + double precision :: dpmax, dtmax, dcmax, dhmax + double precision :: dpmin, dtmin, dcmin, dhmin + + intrinsic trim + + + ! Set counters to zero + icountp = 0 + icountt = 0 + icountc = 0 + + ! Set overall min/max to boundaries of the domain of validity + dpmax = pmax + dpmin = pmin + dtmax = tmax + dtmin = tmin + dcmax = cmax + dcmin = cmin + + ! Check pres + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (pres(i,j,k,ismpl)<pmin) then + ! Set min counter + icountp = icountp + 1 + ! Set new overall minimum + dpmin = min(dpmin,pres(i,j,k,ismpl)) + ! Change pres value to minimum of the domain of validity + pres(i,j,k,ismpl) = pmin + end if + if (pres(i,j,k,ismpl)>pmax) then + ! Set max counter + icountp = icountp + 1 + ! Set new overall maximum + dpmax = max(dpmax,pres(i,j,k,ismpl)) + ! Change pres value to maximum of the domain of validity + pres(i,j,k,ismpl) = pmax + end if + end do + end do + end do + + ! Check temp + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + if (temp(i,j,k,ismpl)<tmin) then + icountt = icountt + 1 + dtmin = min(dtmin,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmin + end if + if (temp(i,j,k,ismpl)>tmax) then + icountt = icountt + 1 + dtmax = max(dtmax,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmax + end if + end do + end do + end do + + ! Check conc + do k = 1, k0 + do j = 1, j0 + do i = 1, i0 + do l = 1, ntrac + if (conc(i,j,k,l,ismpl).gt.cmax) then + icountc = icountc +1 + dcmax = max(dcmax, conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmax + end if + if (conc(i,j,k,l,ismpl)<cmin .and. & + conc(i,j,k,l,ismpl)<-csmin) then + icountc = icountc + 1 + dcmin = min(dcmin,conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmin + end if + if (conc(i,j,k,l,ismpl)<csmin) then + ! very small conc values set to zero to avoid + ! numerically instabilities + conc(i,j,k,l,ismpl) = cmin + end if + end do + end do + end do + end do + +! disable the warning output for linfos(3)==-1 + if (linfos(3)>=0) then + if (icountp/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: pres not in domain of validity of module <', & + trim(def_props), '> at ', icountp, ' points (min', dpmin, & + ', max', dpmax, ')!' + if (icountt/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: temp not in domain of validity of module <', & + trim(def_props), '> at ', icountt, ' points (min', dtmin, & + ', max', dtmax, ')!' + if (icountc/=0) write(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: conc not in domain of validity of module <', & + trim(def_props), '> at ', icountc, ' points (min', dcmin, & + ', max', dcmax, ')!' + + ! error outputs for hard physical concentration boundaries + if (dcmax > cmax) then + write(unit = *, fmt = *) "[E1] Error in check_domain.f90:", & + " maximum concentration dcmax= ", dcmax, & + " larger than allowed maximum value cmax=", cmax + stop + end if + if (dcmin > cmin) then + write(unit = *, fmt = *) "[E2] Error in check_domain.f90:", & + " minimum concentration dcmin= ", dcmin, & + " smaller than allowed minimum value cmin=", cmin + stop + end if + end if + + return + + end subroutine check_domain diff --git a/props/ghe/compf.f90 b/props/ghe/compf.f90 new file mode 100644 index 0000000..86340b0 --- /dev/null +++ b/props/ghe/compf.f90 @@ -0,0 +1,192 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compf calculates compressibility of pure water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility compf [1./Pa] +!> @details +!> compf calculates compressibility of pure water \n +!> given temperature (t, in C), and pressure (p,in Pa)\n +!> at node(i,j,k).\n \n +!> +!> Method: \n +!> +!> compf = 1/rhof d/dP rhof, \n +!> +!> where rhof= water density.\n \n +!> +!> Main source of rhof (water density) approximation, see +!> props/ghe/rhof.f90. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function compf(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv, pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.10000000D+01 + double precision, parameter :: Y1 = 0.17472599D-01 + double precision, parameter :: Y2 = -0.20443098D-04 + double precision, parameter :: Y3 = -0.17442012D-06 + double precision, parameter :: Y4 = 0.49564109D-02 + double precision, parameter :: Y5 = -0.40757664D-04 + double precision, parameter :: Y6 = 0.50676664D-07 + double precision, parameter :: Y7 = 0.50330978D-04 + double precision, parameter :: Y8 = 0.33914814D-06 + double precision, parameter :: Y9 = -0.18383009D-06 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10009476D-02 + double precision, parameter :: Z1 = 0.16812589D-04 + double precision, parameter :: Z2 = -0.24582622D-07 + double precision, parameter :: Z3 = -0.17014984D-09 + double precision, parameter :: Z4 = 0.48841156D-05 + double precision, parameter :: Z5 = -0.32967985D-07 + double precision, parameter :: Z6 = 0.28619380D-10 + double precision, parameter :: Z7 = 0.53249055D-07 + double precision, parameter :: Z8 = 0.30456698D-09 + double precision, parameter :: Z9 = -0.12221899D-09 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt P + double precision :: da + + ! Derivative of denominator wrt P + double precision :: db + + ! Denominator squared + double precision :: b2 + + ! Water density (local) + double precision :: rhof_loc + + ! Derivative of water density wrt P + double precision :: drhodp + + ! Compressibiliy in Mpa + double precision :: compf_mpa + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Water density + rhof_loc = ta/tb + + ! Derivative of numerator + da = Y1 + 2.D0*Y2*p + 3.D0*Y3*p2 + Y7*t + & + 2.D0*Y8*tp + Y9*t2 + + ! Derivative of denominator + db = Z1 + 2.D0*Z2*p + 3.D0*Z3*p2 + Z7*t + & + 2.0*Z8*tp + Z9*t2 + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + drhodp = (da*tb-ta*db)/b2 + + ! Compressibility: (1/rhof_loc) * drhodp [1/MPa] + compf_mpa = drhodp/rhof_loc + + ! Compressibility [1/Pa] + compf = compf_mpa / pa_conv + + return + end function compf diff --git a/props/ghe/compm.f90 b/props/ghe/compm.f90 new file mode 100644 index 0000000..977e772 --- /dev/null +++ b/props/ghe/compm.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compm returns the compressibility of rock matrix +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility of rock [1/Pa] +!> @details +!> compm returns the compressibility [1/Pa] at node(i,j,k) from the +!> input file.\n + double precision function compm(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_comp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + compm = propunit(uindex(i,j,k),idx_comp,ismpl) + + return + + end function compm diff --git a/props/ghe/cpf.f90 b/props/ghe/cpf.f90 new file mode 100644 index 0000000..35568f7 --- /dev/null +++ b/props/ghe/cpf.f90 @@ -0,0 +1,198 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in J/kg/K) +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return cpf [J/kg/K] +!> @details +!> cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in +!> J/kg/K)\n of pure water, given temperature (t, in C), and +!> pressure (p,in Pa)\n at node(i,j,k).\n \n +!> +!> method: c_p = d/dT E, E= fluid enthalpy.\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> pressures 0.001 - 110 MPa,\n +!> temperature 15 - 350 degC\n + double precision function cpf(i,j,k,ismpl) + use arrays, only: pres, temp + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Enthalpy (J/kg) + double precision :: enth + + ! Derivative of enthalpy wrt T (J/kg/K) + double precision :: denthdt + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.25623465D-3 + double precision, parameter :: Y1 = 0.10184405D-2 + double precision, parameter :: Y2 = 0.22554970D-4 + double precision, parameter :: Y3 = 0.34836663D-7 + double precision, parameter :: Y4 = 0.41769866D-2 + double precision, parameter :: Y5 = -0.21244879D-4 + double precision, parameter :: Y6 = 0.25493516D-7 + double precision, parameter :: Y7 = 0.89557885D-4 + double precision, parameter :: Y8 = 0.10855046D-6 + double precision, parameter :: Y9 = -0.21720560D-6 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+1 + double precision, parameter :: Z1 = 0.23513278D-1 + double precision, parameter :: Z2 = 0.48716386D-4 + double precision, parameter :: Z3 = -0.19935046D-8 + double precision, parameter :: Z4 = -0.50770309D-2 + double precision, parameter :: Z5 = 0.57780287D-5 + double precision, parameter :: Z6 = 0.90972916D-9 + double precision, parameter :: Z7 = -0.58981537D-4 + double precision, parameter :: Z8 = -0.12990752D-7 + double precision, parameter :: Z9 = 0.45872518D-8 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Derivative of numerator wrt T + double precision :: da + + ! Derivative of denominator wrt T + double precision :: db + + ! Denominator squared + double precision :: b2 + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Enthalpy + enth = ta/tb + + ! Derivative of numerator + da = Y4 + 2.0d0*Y5*t + 3.0d0*Y6*t2 + Y7*p + & + Y8*p2 + 2.0d0*Y9*tp + + ! Derivative of denominator + db = Z4 + 2.0d0*Z5*t + 3.0d0*Z6*t2 + Z7*p + & + Z8*p2 + 2.0d0*Z9*tp + + ! Denominator squared + b2 = tb*tb + + ! Derivative, quotient rule + denthdt = da/tb - ta*db/b2 + + ! Isobaric heat capacity (J/kg/K) + cpf = denthdt*1.0d6 + + return + + end function cpf diff --git a/props/ghe/disp.f90 b/props/ghe/disp.f90 new file mode 100644 index 0000000..36737bf --- /dev/null +++ b/props/ghe/disp.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign effective diffusivity z direction to cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return assign effective diffusivity +!> @details +!> assign effective diffusivity, called dispersivity in the input +!> file. + double precision function disp(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_df + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + disp = propunit(uindex(i,j,k),idx_df,ismpl) + + return + + end function disp diff --git a/props/ghe/ghe_array.f90 b/props/ghe/ghe_array.f90 new file mode 100644 index 0000000..ba2cb7c --- /dev/null +++ b/props/ghe/ghe_array.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + MODULE work_array_ghe + + + +! IMPLICIT NONE + + + + DOUBLE PRECISION, ALLOCATABLE :: Tu(:,:,:), Td(:,:,:), & + Tout(:,:,:), Tin_new(:,:), Tin(:,:), dTsghe(:), Hghe(:,:),& + dTs(:), Tsghe(:,:), qshe(:,:,:), dTsgheprime(:), & + Tsghe_old(:,:), pghe(:,:), Temp_flip(:,:,:), H_flip(:,:,:), & + pres_flip(:,:,:), Ts(:,:), dTsdepth(:), ypp(:), press(:,:), & + Tsspline(:), pressspline(:), lagrange(:,:,:), yppq(:), & + dpres(:,:) + + INTEGER nt, nghe, tWRITE2, time, endtime, ng, it, k_p, iper, & + tWRITE, np, nr, modswitch + INTEGER, ALLOCATABLE :: ighe(:),jghe(:),fghe(:),k_end(:), & + k_start(:) + DOUBLE PRECISION QF, kw, Cpw, Dw, ru, dz, ruo, Bu, ks, kfill, & + r1, fluid_type, deltatime, ntdouble, Cpwu, Dwu, Cpwd, Dwd, & + depthup, kwd, kwu, dy, Cpwi, Dwi, kwi, kinvisci, & + time_count, dghe + + DOUBLE PRECISION, ALLOCATABLE :: rdu(:), rd(:), rgr(:), ku(:), & + kd(:), kgr(:), Rdb(:), Rudu(:), Rdown(:), Rup(:), Ru_du_cd(:),& + Rb_d_cd(:), depth(:),rb(:) + + INTEGER mp,nl,p, fup, kdepth, ghetype, kl ! l + + END MODULE work_array_ghe diff --git a/props/ghe/ghe_hpr.f90 b/props/ghe/ghe_hpr.f90 new file mode 100644 index 0000000..650d351 --- /dev/null +++ b/props/ghe/ghe_hpr.f90 @@ -0,0 +1,161 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!************************************************************************ +!***** ***** +!***** ***** +!***** ***** +!************************************************************************ +!***** ***** +!***** THIS PROGRAM APPRXIMATES THE EFFECT OF GHE ON THE SUBSURFACE***** +!***** ***** +!***** BY USING AN EFFECTIVE HEAT PRODUCTION ***** +!***** ***** +!***** ***** +!***** dm 270808 modified by jh and rs and dm 250112 ***** +!************************************************************************ +!* +!********************************************************************** + SUBROUTINE GHE_HPROD + USE arrays + USE work_array_ghe + USE mod_genrl + USE mod_genrlc +! IMPLICIT NONE + + DOUBLE PRECISION depth_hpr + +! Alle Sonden gleich...zun�chst + ALLOCATE(dTs(K0)) + +! READ all geometrical borehole parameters************************ + WRITE(*,*) "geometry" + + OPEN(1,FILE='ghe_new.par') + +! Anzahl der GHE + READ(1,*) nghe + + READ(1,*) depth_hpr ! + +! i Stelle GHEs + ALLOCATE(ighe(nghe)) + +! j Stelle GHEs + ALLOCATE(jghe(nghe)) + +! Sondenkopf an der Erdoberfl�che im Modell (k von Shemat) + ALLOCATE(k_end(nghe)) + +! Sondenfu� (k von Shemat) + ALLOCATE(k_start(nghe)) + +! Ort(e) der Sonden + READ(1,*) (ighe(i), jghe(i),k_end(i),i=1,nghe) + CLOSE(1) + + WRITE(*,*) nghe + DO nl=1,nghe + WRITE(*,*) ighe(nl),jghe(nl) + END DO + + OPEN(2,FILE='ghe_ini_new.ini') + +! Anzahl der Perioden + READ(2,*) iper + WRITE(*,*) + WRITE(*,*) ' READING NEW Ground Heat Exchanger model parameters' + WRITE(*,*) + WRITE(*,*) 'Anzahl der Perioden', iper + + ALLOCATE(Tin(iper,4)) + +! Periode (h), Flow an/aus, Leistung (NEU: Leistung (kW) im Gesamtfeld!) + READ(2,*) (Tin(i,1),Tin(i,2),Tin(i,3),i=1,iper) + CLOSE(2) + +! Zeiten in Sekunden + Tin(1,1)=Tin(1,1)*3600.0d0 + + DO i=2,iper + Tin(i,1)=Tin(i,1)*3600.0d0+Tin(i-1,1) + END DO +! auf Sonde und Tiefe verteilt...spaeter Hprod + DO i=1,iper + Tin(i,3)=Tin(i,3)/nghe/depth_hpr + END DO +!----------------% ende einlesen ini------ + +! Hier muss die Anzahl der Sonden ber�cksichtigt werden! + +! ANFANG SCHLEIFE �BER SONDEN ####################### + DO nl=1,nghe +! hier wird variable Tiefe der Sonden gesetzt + k_start(nl)=k_end(nl)-depth_hpr/delz(1)+1 + ! k_end(nl)=K0-k_end(nl) + + WRITE(*,*), 'kdepth', k_start(nl), k_end(nl) +! DO k=k_end(n),k_start(n) +!! setze permeabilitaet an den sonden kl +! kx(ighe(n),jghe(n),K0-k+1,ismpl)=1e-25 +! ky(ighe(n),jghe(n),K0-k+1,ismpl)=1e-25 +! kz(ighe(n),jghe(n),K0-k+1,ismpl)=1e-25 +! END DO +! + END DO +!! ENDE SCHLEIFE �BER SONDEN. ######################### + +! F�r n�chste Routine. + mp=1 + END SUBROUTINE + + +!*******ONE TIME STEP*********************************************************** + +! SUBROUTINE GHETIMESTEP_HPR() +! USE work_array_ghe +! implicit none + +! IF (sdelt.le.Tin(m,1)) THEN +! m=m +! ELSE +! m=m+1 +! END IF +! WRITE(*,*),Tin(m,1) + +!! Anfang Schleife �ber Sonden +! DO n=1,nghe +! IF (Tin(m,2).ne.0) THEN ! An/aus +! DO k=k_end(n),k_start(n)-1 +! qt(ighe(n),jghe(n),K0-k+1)=-Tin(m,3)*1000/& +! (delx(ighe(n))*dely(jghe(n))) +! END DO +! ELSE +! DO k=k_end(n),k_start(n)-1 +! qt(ighe(n),jghe(n),K0-k+1)=0 +! END DO +! END IF +! END DO +!! Ende Schleife �ber Sonden + +! WRITE(*,*), 'Periode: (iper)' , m, 'Zeit', sdelt +! END SUBROUTINE diff --git a/props/ghe/kx.f90 b/props/ghe/kx.f90 new file mode 100644 index 0000000..2b272f0 --- /dev/null +++ b/props/ghe/kx.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in x direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kx returns the permeability in x-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in x-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the x-direction. + double precision function kx(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_kx + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kx = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_kx,ismpl) + +! Wird das Setzen der Werte benoetigt? + +!! ANFANG SCHLEIFE �BER SONDEN ####################### +! DO n=1,nghe +!! hier wird variable Tiefe der Sonden gesetzt +! k_start(n)=K0-(k_end(n)-depth_hpr/delz(1)) +! k_end(n)=K0-k_end(n) +! +! WRITE(*,*), 'kdepth', k_start(n), k_end(n) +! DO l=k_end(n),k_start(n) +!! setze permeabilitaet an den sonden kl +! IF (ighe(n).eq.i && jghe(n).eq.j && (K0-l+1).eq.k) +! kx=1e-25 +! END IF +! END DO +! END DO +!! ENDE SCHLEIFE �BER SONDEN. ######################### + + return + + end function kx diff --git a/props/ghe/ky.f90 b/props/ghe/ky.f90 new file mode 100644 index 0000000..c9e052b --- /dev/null +++ b/props/ghe/ky.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in y direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> ky returns the permeability in y-direction [m2] at node(i,j,k) from +!> the input file.\n\n +!> +!> The permeability in y-direction is the product of the permeability +!> in z-direction and the anisotropy factor for the y-direction. + double precision function ky(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz, idx_an_ky + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + ky = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ky,ismpl) + +! Wird das Setzen der Werte benoetigt? + +!! ANFANG SCHLEIFE �BER SONDEN ####################### +! DO n=1,nghe +!! hier wird variable Tiefe der Sonden gesetzt +! k_start(n)=K0-(k_end(n)-depth_hpr/delz(1)) +! k_end(n)=K0-k_end(n) +! +! WRITE(*,*), 'kdepth', k_start(n), k_end(n) +! DO l=k_end(n),k_start(n) +!! setze permeabilitaet an den sonden kl +! IF (ighe(n).eq.i && jghe(n).eq.j && (K0-l+1).eq.k) +! ky=1e-25 +! END IF +! END DO +! END DO +!! ENDE SCHLEIFE �BER SONDEN. ######################### + + return + + end function ky diff --git a/props/ghe/kz.f90 b/props/ghe/kz.f90 new file mode 100644 index 0000000..0280f8e --- /dev/null +++ b/props/ghe/kz.f90 @@ -0,0 +1,69 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign permeability in z direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details +!> kz returns the permeability in z-direction[m2] at node(i,j,k) from +!> the input file.\n + double precision function kz(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_kz + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + kz = propunit(uindex(i,j,k),idx_kz,ismpl) + + +! Wird das Setzen der Werte benoetigt? + +!! ANFANG SCHLEIFE �BER SONDEN ####################### +! DO n=1,nghe +!! hier wird variable Tiefe der Sonden gesetzt +! k_start(n)=K0-(k_end(n)-depth_hpr/delz(1)) +! k_end(n)=K0-k_end(n) +! +! WRITE(*,*), 'kdepth', k_start(n), k_end(n) +! DO l=k_end(n),k_start(n) +!! setze permeabilitaet an den sonden kl +! IF (ighe(n).eq.i && jghe(n).eq.j && (K0-l+1).eq.k) +! kz=1e-25 +! END IF +! END DO +! END DO +!! ENDE SCHLEIFE �BER SONDEN. ######################### + + return + + end function kz diff --git a/props/ghe/lamf.f90 b/props/ghe/lamf.f90 new file mode 100644 index 0000000..ae283bd --- /dev/null +++ b/props/ghe/lamf.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate the thermal conductivity kf in W/(m*K) of water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity [W/(m*K)] +!> @details +!> Calculate the thermal conductivity kf in W/(m*K) of freshwater, +!> given temperature in degC. Thermal conductivity of freshwater, kfw +!> is calculated using the Phillips (1981) formulation (page 8). \n\n +!> +!> Source:\n\n +!> +!> Phillips, S., Igbene, A., Fair, J., Ozbek, H., & Tavana, M., +!> Technical databook for geothermal energy utilization (1981). +!> http://dx.doi.org/10.2172/6301274 \n\n +!> +!> Range of validity: 20 to 330 degC\n\n +!> +!> temperature tlocal in [C]\n + double precision function lamf(i,j,k,ismpl) + use arrays, only: temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Monomials of temperatures quotient + double precision :: tr, tr2, tr3, tr4 + + ! Coefficients of approximation + double precision, parameter :: c0 = -0.92247d0 + double precision, parameter :: c1 = 2.8395d0 + double precision, parameter :: c2 = 1.8007d0 + double precision, parameter :: c3 = 0.52577d0 + double precision, parameter :: c4 = 0.07344d0 + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Monomials of temperature quotient + tr = (tlocal+273.15d0)/273.15d0 + tr2 = tr*tr + tr3 = tr2*tr + tr4 = tr3*tr + + ! Thermal conductivity [W/(m*K)] + lamf = (c0 + c1*tr - c2*tr2 + c3*tr3 - c4*tr4) + + return + + end function lamf diff --git a/props/ghe/lamm.f90 b/props/ghe/lamm.f90 new file mode 100644 index 0000000..42ede46 --- /dev/null +++ b/props/ghe/lamm.f90 @@ -0,0 +1,128 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate temperature dependent thermal conductivity +!> @param[in] lammref thermal conductivity from input file +!> @param[in] tlocal temperature +!> @param[in] tref reference temperature +!> @param[in] ismpl local sample index +!> @return temperature dependent thermal conductivity +!> @details +!> calculate temperature dependent thermal conductivity\n +!> +!> lam_zoth/haenel = (770degC/(350degC+T) + 0.7) W/mK +!> +!> If T > 800degC, use the formula from zoth & haenel, 1988. \n +!> +!> lamm = lam_zoth/haenel +!> +!> If T < 800degC, use the same formula with a factor `fct` +!> +!> lamm = fct * lam_zoth/haenel +!> +!> The factor `fct` introduces an additional temperature dependence +!> such that\n +!> 1. `lamm(20degC) = lammref`\n +!> 2. `lamm(800degC) = lam_zoth/haenel(800degC)\n\n +!> +!> Thus, the thermal conductivity in the input file should resemble +!> information about the value of the thermal conductivity of the +!> matrix at temperature 20 degC.\n\n +!> +!> Sources: \n +!> Zoth, G., & Haenel, R, Handbook of terrestrial heat-flow density +!> determination, (1988), Appendix 10.1 Thermal +!> Conductivity. http://dx.doi.org/10.1007/978-94-009-2847-3\n\n +!> +!> Lehmann, H., Wang, K., & Clauser, C., Parameter identification and +!> uncertainty analysis for heat transfer at the ktb drill site using +!> a 2-d inverse method, Tectonophysics, 291(1-4), 179–194 +!> (1998). Section 2.2 http://dx.doi.org/10.1016/s0040-1951(98)00039-0 +!> \n + double precision function lamm(lammref,tlocal,tref,ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + ! Thermal conductivity of matrix at tref=20degC + double precision, intent (in) :: lammref + + ! Local temperature [degC] + double precision, intent (in) :: tlocal + + ! Reference temperature [20 degC] + double precision, intent (in) :: tref + + ! Upper limit temperature, where the approximation becomes + ! equal to the general Zoth/Haenel formula + double precision, parameter :: tlimit = 800.0d0 + + ! lam_zoth/haenel at tlocal + double precision :: lamm_zh + + ! lam_zoth/haenel at tref + double precision :: lamm_zhref + + ! Reference Interpolation-factor + double precision :: fctref + + ! Weight: Quotient of temperature differences + double precision :: twgt + + ! Interpolation factor + double precision :: fct + + + if (tlocal > tlimit) then + + ! lam_zoth/haenel at tlocal + lamm = 770.0d0/(350.0d0+tlocal) + 0.7D0 + + else + + ! lam_zoth/haenel at tlocal + lamm_zh = 770.0d0/(350.0d0+tlocal) + 0.7d0 + + ! lam_zoth/haenel at tref + lamm_zhref = 770.0d0/(350.0d0+tref) + 0.7d0 + + ! Reference Interpolation-factor: Input lamm at tref divided + ! by lam_zoth/haenel at tref + fctref = lammref/lamm_zhref + + ! Quotient of temperature differences, local minus reference + ! divided by limit minus reference + twgt = (tlocal-tref)/(tlimit-tref) + + ! Interpolation factor between fctref at tref and 1 at tlimit + fct = fctref*(1-twgt) + twgt + + ! Final lam: input at tref and lam_zoth/haenel at tlimit + lamm = fct*lamm_zh + + end if + + return + + end function lamm diff --git a/props/ghe/lx.f90 b/props/ghe/lx.f90 new file mode 100644 index 0000000..1d17aeb --- /dev/null +++ b/props/ghe/lx.f90 @@ -0,0 +1,66 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lx[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION lx(i,j,k,ismpl) + use arrays + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION plocal, tlocal, fluid, lamunit, lamf, & + porlocal, lamm + EXTERNAL lamf, lamm + + +! ploCal = pres(i,j,k,ismpl)*Pa_Conv1 + tlocal = temp(i,j,k,ismpl) + fluid = lamf(i,j,k,ismpl) + ui = uindex(i,j,k) + porlocal = propunit(ui,idx_por,ismpl) + lamunit = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_lx, & + ismpl) +! lx= +! * (1.d0-porlocal)*lamm(lamunit,tlocal,tref,ismpl)+porlocal*fluid + lx = lamm(lamunit,tlocal,tref,ismpl) + IF (lx<=0.D0 .OR. fluid<=0.D0) THEN + WRITE(*,*) 'warning: "lx" computes bad math !', lx, fluid, & + tlocal + ELSE + lx = lx**(1.D0-porlocal)*fluid**porlocal + END IF + + RETURN + END diff --git a/props/ghe/ly.f90 b/props/ghe/ly.f90 new file mode 100644 index 0000000..ee8426b --- /dev/null +++ b/props/ghe/ly.f90 @@ -0,0 +1,65 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity ly[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION ly(i,j,k,ismpl) + use arrays + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION plocal, tlocal, solid, fluid, lamunit, lamf, & + porlocal, tkelvin, lamm + EXTERNAL lamf, lamm + + +! ploCal = pres(i,j,k,ismpl)*Pa_Conv1 + tlocal = temp(i,j,k,ismpl) + fluid = lamf(i,j,k,ismpl) + ui = uindex(i,j,k) + porlocal = propunit(ui,idx_por,ismpl) + lamunit = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_ly, & + ismpl) +! ly= +! & (1.d0-porlocal)*lamm(lamunit,tlocal,tref,ismpl)+porlocal*fluid + ly = lamm(lamunit,tlocal,tref,ismpl) + IF (ly<=0.D0 .OR. fluid<=0.D0) THEN + WRITE(*,*) 'warning: "ly" computes bad math !' + ELSE + ly = ly**(1.D0-porlocal)*fluid**porlocal + END IF + + RETURN + END diff --git a/props/ghe/lz.f90 b/props/ghe/lz.f90 new file mode 100644 index 0000000..4414512 --- /dev/null +++ b/props/ghe/lz.f90 @@ -0,0 +1,64 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION lz(i,j,k,ismpl) + use arrays + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION plocal, tlocal, solid, fluid, lamunit, lamf, & + porlocal, tkelvin, lamm + EXTERNAL lamf, lamm + + +! ploCal = pres(i,j,k,ismpl)*Pa_Conv1 + tlocal = temp(i,j,k,ismpl) + fluid = lamf(i,j,k,ismpl) + ui = uindex(i,j,k) + porlocal = propunit(ui,idx_por,ismpl) + lamunit = propunit(ui,idx_lz,ismpl) +! lz= +! * (1.d0-porlocal)*lamm(lamunit,tlocal,tref,ismpl)+porlocal*fluid + lz = lamm(lamunit,tlocal,tref,ismpl) + IF (lz<=0.D0 .OR. fluid<=0.D0) THEN + WRITE(*,*) 'warning: "lz" computes bad math !' + ELSE + lz = lz**(1.D0-porlocal)*fluid**porlocal + END IF + + RETURN + END diff --git a/props/ghe/por.f90 b/props/ghe/por.f90 new file mode 100644 index 0000000..d4be904 --- /dev/null +++ b/props/ghe/por.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign porosity to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return porosity porlocal [-] +!> @details +!> por returns the porosity [-] at node(i,j,k) from the input file.\n + double precision function por(i,j,k,ismpl) + use arrays, only: propunit, uindex, idx_por + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + + por = propunit(uindex(i,j,k),idx_por,ismpl) + + return + + end function por diff --git a/props/ghe/props_check.f90 b/props/ghe/props_check.f90 new file mode 100644 index 0000000..8fa2c61 --- /dev/null +++ b/props/ghe/props_check.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current PROPS choice +!> @param[in] ismpl local sample index +!> @details +!> Check the local/current PROPS ldef_props against the PROPS choice +!> in the input file (def_props). + subroutine props_check(ismpl) + use mod_genrlc, only: def_props + + implicit none + + ! Sample index + integer :: ismpl + + ! Local PROPS + character (len=10), parameter :: ldef_props = "ghe" + + ! Test options of command line input + logical, external :: test_option + + intrinsic trim + + +#ifndef PROPS_ghe + write(*,'(3A)') 'error: this source was written for PROPS=', & + ldef_props, & + ', please correct this check in "props_check.f"!' + stop +#endif + if ( .not. test_option('PROPS='//trim(def_props))) then + if (ldef_props/=def_props) then + write(*,'(7A)') 'Error: model file needs an executable', & + ' build from PROPS=', trim(def_props), & + ', but the current', ' consist of PROPS=', & + trim(ldef_props), '!' + stop + end if + end if + + return + + end subroutine props_check diff --git a/props/ghe/props_end.f90 b/props/ghe/props_end.f90 new file mode 100644 index 0000000..9357557 --- /dev/null +++ b/props/ghe/props_end.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper finishing property module +!> @param[in] ismpl local sample index +!> @details +!> For ghe: Dummy Wrapper. + subroutine props_end(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine props_end diff --git a/props/ghe/props_init.f90 b/props/ghe/props_init.f90 new file mode 100644 index 0000000..c583244 --- /dev/null +++ b/props/ghe/props_init.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper initializing property module +!> @param[in] ismpl local sample index +!> @details +!> Wrapper for calling read_props and check_props. + subroutine props_init(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + CALL read_props(ismpl) + + CALL check_props(ismpl) + + return + + end subroutine props_init diff --git a/props/ghe/qc.f90 b/props/ghe/qc.f90 new file mode 100644 index 0000000..dc3b9e0 --- /dev/null +++ b/props/ghe/qc.f90 @@ -0,0 +1,55 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign transport production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @return transport production +!> @details +!> Assign transport production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> transport production to exist.\n + double precision function qc(i,j,k,spec,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Species index + integer, intent (in) :: spec + + ! Sample index + integer :: ismpl + + ! No transport production + qc = 0.0d0 + + return + + end function qc diff --git a/props/ghe/qf.f90 b/props/ghe/qf.f90 new file mode 100644 index 0000000..6ed3011 --- /dev/null +++ b/props/ghe/qf.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign flow production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return flow production +!> @details +!> Assign flow production to cell. \n\n +!> +!> Hardcoded to zero, use only if you really know that you want +!> flow production to exist.\n + double precision function qf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + qf = 0.0d0 + + return + + end function qf diff --git a/props/ghe/qt.f90 b/props/ghe/qt.f90 new file mode 100644 index 0000000..16906b8 --- /dev/null +++ b/props/ghe/qt.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign heat production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return heat production + DOUBLE PRECISION FUNCTION qt(i,j,k,ismpl) + USE work_array_ghe + USE arrays + ! USE mod_genrl + ! USE mod_genrlc +! IMPLICIT NONE + INTEGER i, j, k, ismpl + ! DOUBLE PRECISION por + +! vr : aCtor (1-por) ? +! por=propunit(uindex(i,j,k),idx_por,ismpl) +! qt = (1.d0- por)*(propunit(uindex(i,j,k),idx_q,ismpl) + qt = propunit(uindex(i,j,k),idx_q,ismpl) + + IF (simtime(ismpl).le.Tin(mp,1)) THEN + mp=mp + + ELSE + mp=mp+1 + END IF +! WRITE(*,*),Tin(m,1) + +! Anfang Schleife �ber Sonden + DO nl=1,nghe + IF (Tin(mp,2).ne.0) THEN ! An/aus +! DO kl=k_start(nl),k_end(nl) + IF (i.eq.(ighe(nl)).and.(j.eq.jghe(nl)).and.((k.ge.k_start(nl)) & + .and.(k.le.k_end(nl)))) THEN + qt = -Tin(mp,3)*1000/& + (delx(ighe(nl))*dely(jghe(nl))) +! ELSE +! qt =propunit(uindex(i,j,k),idx_q,ismpl) + END IF + ! END DO + ELSE + qt=propunit(uindex(i,j,k),idx_q,ismpl) + END IF + END DO +! Ende Schleife �ber Sonden + +! WRITE(*,*), 'Periode: (iper)' , mp, 'Zeit', simtime(ismpl) + + RETURN + END diff --git a/props/ghe/rce.f90 b/props/ghe/rce.f90 new file mode 100644 index 0000000..4811222 --- /dev/null +++ b/props/ghe/rce.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates volumetric heat capacity of the cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return volumetric heat capacity +!> @details +!> calculates volumetric heat capacity of the system +!> matrix-porosity [J/(K*m3)].\n + double precision function rhoceff(i,j,k,ismpl) + + use arrays, only: temp + ! use mod_temp + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Local temperature [degC] + double precision :: tlocal + + ! Local porosity [-] + double precision :: porlocal + double precision, external :: por + + ! Matrix fraction in cell + double precision :: fm + + ! Fluid fraction in cell + double precision :: ff + + ! Heat capacity of the matrix + double precision, external :: rhocm + + ! Heat capacity of the fluid + double precision, external :: rhocf + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Local porosity + porlocal = por(i,j,k,ismpl) + + ! Matrix fraction + fm = 1.D0 - porlocal + + ! Fluid fraction + ff = porlocal + + ! Heat capacity in cell, arithmetic mean + rhoceff = ff*rhocf(i,j,k,ismpl) + fm*rhocm(i,j,k,ismpl) + + return + + end function rhoceff diff --git a/props/ghe/read_props.f90 b/props/ghe/read_props.f90 new file mode 100644 index 0000000..cb64735 --- /dev/null +++ b/props/ghe/read_props.f90 @@ -0,0 +1,37 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief read additional user defined parameters +!> @param[in] ismpl local sample index +!> @details +!> For ghe: So far no additional user defined parameters. + subroutine read_props(ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + + return + + end subroutine read_props diff --git a/props/ghe/rhocf.f90 b/props/ghe/rhocf.f90 new file mode 100644 index 0000000..ce6d69f --- /dev/null +++ b/props/ghe/rhocf.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity times density of water. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> calculates volumetric heat capacity of the fluid [J/(K*m3)].\n + double precision function rhocf(i,j,k,ismpl) + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Density of fluid [kg/m3] + double precision :: rfluid + double precision, external :: rhof + + ! Water isobaric head capacity [J/(K*kg)] + double precision :: cfluid + double precision, external :: cpf + + ! water density [kg/m**3] + rfluid = rhof(i,j,k,ismpl) + + ! water isobaric heat capacity [J/(kg*K)] + cfluid = cpf(i,j,k,ismpl) + + ! water volumetric heat capacity [J/(K*m3)] + rhocf = rfluid*cfluid + + return + + end function rhocf diff --git a/props/ghe/rhocm.f90 b/props/ghe/rhocm.f90 new file mode 100644 index 0000000..68dfbb2 --- /dev/null +++ b/props/ghe/rhocm.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of rock. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoc [W/(m*K)] +!> @details +!> temperature tlocal in [C]\n\n +!> +!> Under input file "# rhocm", the temperature variation coefficients +!> cma1, cma2, cma3 can be set. \n +!> Default: cma1 = 1.0d0, cma2 = cma3 = 0.0d0 + double precision function rhocm(i,j,k,ismpl) + use arrays, only: temp, propunit, uindex, idx_rc + use mod_temp, only: cma1, cma2, cma3 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Volumetric heat capacity from input file [J/(kg*m3)] + rhocm = propunit(uindex(i,j,k),idx_rc,ismpl)* & + (cma1+cma2*tlocal+cma3*tlocal*tlocal) + + return + + end function rhocm diff --git a/props/ghe/rhof.f90 b/props/ghe/rhof.f90 new file mode 100644 index 0000000..0ce5604 --- /dev/null +++ b/props/ghe/rhof.f90 @@ -0,0 +1,169 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure water, +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rho [kg/m^3] +!> @details +!> rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure +!> water, given temperature (t, in degC), and pressure (p,in Pa) at +!> node(i,j,k)\n \n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function rhof(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.10000000D+01 + double precision, parameter :: Y1 = 0.17472599D-01 + double precision, parameter :: Y2 = -0.20443098D-04 + double precision, parameter :: Y3 = -0.17442012D-06 + double precision, parameter :: Y4 = 0.49564109D-02 + double precision, parameter :: Y5 = -0.40757664D-04 + double precision, parameter :: Y6 = 0.50676664D-07 + double precision, parameter :: Y7 = 0.50330978D-04 + double precision, parameter :: Y8 = 0.33914814D-06 + double precision, parameter :: Y9 = -0.18383009D-06 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10009476D-02 + double precision, parameter :: Z1 = 0.16812589D-04 + double precision, parameter :: Z2 = -0.24582622D-07 + double precision, parameter :: Z3 = -0.17014984D-09 + double precision, parameter :: Z4 = 0.48841156D-05 + double precision, parameter :: Z5 = -0.32967985D-07 + double precision, parameter :: Z6 = 0.28619380D-10 + double precision, parameter :: Z7 = 0.53249055D-07 + double precision, parameter :: Z8 = 0.30456698D-09 + double precision, parameter :: Z9 = -0.12221899D-09 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Water density + rhof = ta/tb + + return + + end function rhof diff --git a/props/ghe/visf.f90 b/props/ghe/visf.f90 new file mode 100644 index 0000000..d88452d --- /dev/null +++ b/props/ghe/visf.f90 @@ -0,0 +1,167 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return visf [Pa s] +!> @details +!> rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water,\n +!> given temperature (t, in C), and pressure (p,in Pa) at node(i,j,k)\n\n +!> +!> Main source Zyvoloski1997: \n +!> +!> Zyvoloski, G.A., Robinson, B.A., Dash, Z.V., & Trease, L.L. Summary +!> of the models and methods for the FEHM application - a +!> finite-element heat- and mass-transfer code. United +!> States. doi:10.2172/565545. \n \n +!> +!> See Section 8.4.3. of Zyvoloski1997 for an explanation of the +!> "Rational function approximation" used in this subroutine. \n \n +!> The approximation uses the table of coefficients in Appendix 10 of +!> Zyvoloski1997.\n +!> +!> Alternative source (same text, more modern, without doi): \n +!> https://fehm.lanl.gov/orgs/ees/fehm/pdfs/fehm_mms.pdf \n \n +!> +!> The table of coefficients from Zyvoloski1997 describes the physical +!> values found in Haar1984: \n +!> +!> Lester Haar, John Gallagher, George Kell, NBS/NRC Steam Tables: +!> Thermodynamic and Transport Properties and Computer Programs for +!> Vapor and Liquid States of Water in SI Units, Hemisphere Publishing +!> Corporation, Washington, 1984. \n \n +!> +!> range of validity:\n +!> - pressures 0.001 - 110 MPa,\n +!> - temperature 15 - 360 degC\n + double precision function visf(i,j,k,ismpl) + use arrays, only: temp, pres + use mod_flow, only: pa_conv1 + + implicit none + + ! Location indices + integer, intent (in) :: i + integer, intent (in) :: j + integer, intent (in) :: k + + ! Sample index + integer :: ismpl + + ! Temperature (degC) + double precision :: tlocal + + ! Pressure (MPa) + double precision :: plocal + + ! Monomials of temperature and pressure + double precision :: t, t2, t3 + double precision :: p, p2, p3, p4 + double precision :: tp, t2p, tp2 + + ! Coefficients of numerator of rational function approximation + double precision, parameter :: Y0 = 0.17409149D-02 + double precision, parameter :: Y1 = 0.18894882D-04 + double precision, parameter :: Y2 = -0.66439332D-07 + double precision, parameter :: Y3 = -0.23122388D-09 + double precision, parameter :: Y4 = -0.31534914D-05 + double precision, parameter :: Y5 = 0.11120716D-07 + double precision, parameter :: Y6 = -0.48576020D-10 + double precision, parameter :: Y7 = 0.28006861D-07 + double precision, parameter :: Y8 = 0.23225035D-09 + double precision, parameter :: Y9 = 0.47180171D-10 + + ! Coefficients of denominator of rational function approximation + double precision, parameter :: Z0 = 0.10000000D+01 + double precision, parameter :: Z1 = 0.10523153D-01 + double precision, parameter :: Z2 = -0.22658391D-05 + double precision, parameter :: Z3 = -0.31796607D-06 + double precision, parameter :: Z4 = 0.29869141D-01 + double precision, parameter :: Z5 = 0.21844248D-03 + double precision, parameter :: Z6 = -0.87658855D-06 + double precision, parameter :: Z7 = 0.41690362D-03 + double precision, parameter :: Z8 = -0.25147022D-05 + double precision, parameter :: Z9 = 0.22144660D-05 + + ! Numerator and denominator of rational function approximation + double precision :: ta, tb + + ! Local Pressure in MPa + plocal = pres(i,j,k,ismpl)*pa_conv1 + + ! Local Temperature in degC + tlocal = temp(i,j,k,ismpl) + + ! Temperature out of bounds + if (tlocal > 360.0d0) then + write (*,*) "[E1]: Error: Temperature (",& + tlocal,") out of bounds (> 360 degC) at ", i,j,k + stop + end if + if (tlocal < 0.0d0) then + ! Relax table boundary of 15degC to error boundary 0degC + write (*,*) "[E2]: Error: Temperature (",& + tlocal,") out of bounds (< 0 degC) at ", i,j,k + stop + end if + + ! Pressure out of bounds + if (plocal > 110.0d0) then + write (*,*) "[E3]: Error: Pressure (",& + plocal,") out of bounds (> 110 MPa) at ", i,j,k + stop + end if + if (plocal < 0.001d0) then + write (*,*) "[E4]: Error: Pressure (",& + plocal,") out of bounds (< 0.001 MPa) at ", i,j,k + stop + end if + + ! Compute monomials in pressure and temperature + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + tp2 = t*p2 + t2p = t2*p + + ! Numerator of rational function approximation + ta = Y0 + Y1*p + Y2*p2 + Y3*p3 + Y4*t + & + Y5*t2 + Y6*t3 + Y7*tp + Y8*tp2 + Y9*t2p + + ! Denominator of rational function approximation + tb = Z0 + Z1*p + Z2*p2 + Z3*p3 + Z4*t + & + Z5*t2 + Z6*t3 + Z7*tp + Z8*tp2 + Z9*t2p + + ! Viscosity + visf = ta/tb + + return + + end function visf diff --git a/props/ice/check_domain.f90 b/props/ice/check_domain.f90 new file mode 100644 index 0000000..7213e66 --- /dev/null +++ b/props/ice/check_domain.f90 @@ -0,0 +1,115 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief domain of validity for module ice +!> @param[in] ismpl local sample index + SUBROUTINE check_domain(ismpl) + use arrays + use mod_genrl + use mod_genrlc + use mod_conc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l + + +! counts the directions (thickness large enough) + INTEGER icountp, icountt, icountc +! [csmin] reasonable physical value when not [cmin] + DOUBLE PRECISION pmin, pmax, tmin, tmax, cmin, csmin, cmax, & + hmin, hmax, dpmax, dtmax, dcmax, dhmax, dpmin, dtmin, dcmin, & + dhmin + PARAMETER (pmin=0.01D6,pmax=150.D6,tmin=-60.0D0,tmax=350.0, & + cmin=0.D0,csmin=1.D-30,cmax=1.D0) + INTRINSIC trim + + + icountp = 0 + icountt = 0 + icountc = 0 + dpmax = pmax + dpmin = pmin + dtmax = tmax + dtmin = tmin + dcmax = cmax + dcmin = cmin + + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + IF (pres(i,j,k,ismpl)<pmin) THEN + icountp = icountp + 1 + dpmin = min(dpmin,pres(i,j,k,ismpl)) + pres(i,j,k,ismpl) = pmin + END IF + IF (pres(i,j,k,ismpl)>pmax) THEN + icountp = icountp + 1 + dpmax = max(dpmax,pres(i,j,k,ismpl)) + pres(i,j,k,ismpl) = pmax + END IF + IF (temp(i,j,k,ismpl)<tmin) THEN + icountt = icountt + 1 + dtmin = min(dtmin,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmin + END IF + IF (temp(i,j,k,ismpl)>tmax) THEN + icountt = icountt + 1 + dtmax = max(dtmax,temp(i,j,k,ismpl)) + temp(i,j,k,ismpl) = tmax + END IF + DO l = 1, ntrac + IF (conc(i,j,k,l,ismpl)<cmin) THEN + icountc = icountc + 1 + dcmin = min(dcmin,conc(i,j,k,l,ismpl)) + conc(i,j,k,l,ismpl) = cmin + END IF +!aw-later if (conc(i,j,k,l,ismpl).gt.cmax) then +!aw-later icountc = icountc +1 +!aw-later dcmax = max(dcmax, conc(i,j,k,l,ismpl)) +!aw-later conc(i,j,k,l,ismpl) = cmax +!aw-later endif +! use reasonable physical value [csmin] + IF (conc(i,j,k,l,ismpl)<csmin) THEN +! to avoid numerically instabilities + conc(i,j,k,l,ismpl) = cmin + END IF + END DO + END DO + END DO + END DO + + IF (icountp/=0) WRITE(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: pres not in domain of validity of module <', & + trim(def_props), '> at ', icountp, ' points (min', dpmin, & + ', max', dpmax, ')!' + IF (icountt/=0) WRITE(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: temp not in domain of validity of module <', & + trim(def_props), '> at ', icountt, ' points (min', dtmin, & + ', max', dtmax, ')!' + IF (icountc/=0) WRITE(*,'(3A,1I8,1A,1e16.7,1A,1e16.7,1A)') & + 'warning: conc not in domain of validity of module <', & + trim(def_props), '> at ', icountc, ' points (min', dcmin, & + ', max', dcmax, ')!' + + RETURN + END diff --git a/props/ice/compf.f90 b/props/ice/compf.f90 new file mode 100644 index 0000000..a51a2e9 --- /dev/null +++ b/props/ice/compf.f90 @@ -0,0 +1,115 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compf calculates compressibility of pure water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return compressibility compf [1./Pa] +!> @details +!> compf calculates compressibility of pure water \n +!> given temperature (t, in C), and pressure (p,in Pa)\n +!> at node(plocal,tlocal).\n +!> method: compf = 1/rhof d/dP rhof, rhof= fluid density.\n +!> derived from the formulation given in:\n +!> zylkovskij et al: models and methods summary for\n +!> the fehmn application,\n +!> ecd 22, la-ur-94-3787, los alamos nl, 1994.\n +!> range of validity:\n +!> pressures 0.01 - 110 MPa,\n +!> temperature 0.001 - 350 �C and -46�C - 0�C\n +!> input:\n +!> pressure plocal [Pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION compf(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION cf(20), bf(6) + DOUBLE PRECISION ta, tb, da, db, b2, rhof_loc, drhodp, t, t2, t3, & + tlocal, tred, p, p2, p3, p4, plocal, tp, t2p, tp2 + + DATA cf/0.10000000D+01, 0.17472599D-01, -0.20443098D-04, & + -0.17442012D-06, 0.49564109D-02, -0.40757664D-04, & + 0.50676664D-07, 0.50330978D-04, 0.33914814D-06, & + -0.18383009D-06, 0.10009476D-02, 0.16812589D-04, & + -0.24582622D-07, -0.17014984D-09, 0.48841156D-05, & + -0.32967985D-07, 0.28619380D-10, 0.53249055D-07, & + 0.30456698D-09, -0.12221899D-09/ + +! new: after Speedy (1987) for T < 0 to -46 C + DATA bf/20.D0, 4.12D0, -1.13D0, 77.817D0, -78.143D0, 54.29D0/ +! end new + + plocal = pres(i,j,k,ismpl)*pa_conv1 + tlocal = temp(i,j,k,ismpl) + IF (tlocal<-45D0) tlocal = -45.D0 + + IF (tlocal<0.D0) THEN +! new: after Speedy (1987) for T < 0 to -46 C + tred = (tlocal+273.15D0-227.15D0)/227.15D0 + compf = bf(1)/sqrt(tred) + bf(2) + bf(3)*tred + & + bf(4)*tred*tred + bf(5)*tred*tred*tred + & + bf(6)*tred*tred*tred*tred + compf = compf*1.D-11 + ELSE +! end new + IF (tlocal>300.D0) tlocal = 300.D0 + + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + t2p = t2*p + tp2 = t*p2 + +! liquid density + ta = cf(1) + cf(2)*p + cf(3)*p2 + cf(4)*p3 + cf(5)*t + & + cf(6)*t2 + cf(7)*t3 + cf(8)*tp + cf(10)*t2p + cf(9)*tp2 + tb = cf(11) + cf(12)*p + cf(13)*p2 + cf(14)*p3 + cf(15)*t + & + cf(16)*t2 + cf(17)*t3 + cf(18)*tp + cf(20)*t2p + & + cf(19)*tp2 + rhof_loc = ta/tb + +! derivative C C2+2*C3*p+3*C4*p^2+C8*t+C10*t^2+2*C9*t*p + da = cf(2) + 2.D0*cf(3)*p + 3.D0*cf(4)*p2 + cf(8)*t + & + 2.D0*cf(9)*tp + cf(10)*t2 +! derivative C12+2*C13*p+3*C14*p^2+C18*t+C20*t^2+2*C19*t*p + db = cf(12) + 2.D0*cf(13)*p + 3.D0*cf(14)*p2 + cf(18)*t + & + 2.0*cf(19)*tp + cf(20)*t2 + + b2 = tb*tb + drhodp = (da*tb-ta*db)/b2 +! Compf=rhof_loc/drhodp +! Compf=rhof_loc + compf = 1.E-6*drhodp/rhof_loc + END IF + + RETURN + END diff --git a/props/ice/compm.f90 b/props/ice/compm.f90 new file mode 100644 index 0000000..c0f72fd --- /dev/null +++ b/props/ice/compm.f90 @@ -0,0 +1,46 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief compm calculates compressibility of rock +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!#> @return compm compressibility of rock +!> @details +!> compm calculates compressibility of rock\n +!> given temperature (t, in C), and pressure (p,in Pa)\n +!> at node(i,j,k).\n + DOUBLE PRECISION FUNCTION compm(i,j,k,ismpl) + + + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + + compm = propunit(uindex(i,j,k),idx_comp,ismpl) + + RETURN + END diff --git a/props/ice/compw.f90 b/props/ice/compw.f90 new file mode 100644 index 0000000..5434951 --- /dev/null +++ b/props/ice/compw.f90 @@ -0,0 +1,69 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + DOUBLE PRECISION FUNCTION compw(p,t) + + IMPLICIT NONE + + DOUBLE PRECISION t, p + DOUBLE PRECISION a, b, c, d, e, f, g + DOUBLE PRECISION rhow_loc +! external rhow_loc + DOUBLE PRECISION a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, & + d2, e0, e1, e2, f0, f1, f2, g0, g1, g2 + DATA a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2, e0, e1, & + e2, f0, f1, f2, g0, g1, g2/ + 9.99792877961606D+02, & + + 5.07605113140940D-04, -5.2842547816413D-10, & + + 5.13864847162196D-02, -3.61991396354483D-06, & + + 7.97204102509724D-12, -7.53557031774437D-03, & + + 6.37212093275576D-05, -1.66203631393248D-13, & + + 4.60380647957350D-05, -5.61299059722121D-10, & + + 1.80924436489400D-15, -2.26651454175013D-07, & + + 3.36874416675978D-12, -1.30352149261326D-17, & + + 6.14889851856743D-10, -1.06165223196756D-14, & + + 4.75014903737416D-20, -7.39221950969522D-13, & + + 1.42790422913922D-17, -7.13130230531541D-23/ + +! liquid density + a = a0 + a1*p + a2*p**2 + b = b0 + b1*p + b2*p**2 + c = c0 + c1*p + c2*p**2 + d = d0 + d1*p + d2*p**2 + e = e0 + e1*p + e2*p**2 + f = f0 + f1*p + f2*p**2 + g = g0 + g1*p + g2*p**2 + + rhow_loc = a + b*t + c*t**2 + d*t**3 + e*t**4 + f*t**5 + g*t**6 + +! liquid Compressibility + a = a1 + 2*a2*p + b = b1 + 2*b2*p + c = c1 + 2*c2*p + d = d1 + 2*d2*p + e = e1 + 2*e2*p + f = f1 + 2*f2*p + g = g1 + 2*g2*p + + compw = (b*t+c*t**2+d*t**3+e*t**4+f*t**5+g*t**6)/rhow_loc + + RETURN + END diff --git a/props/ice/cpf.f90 b/props/ice/cpf.f90 new file mode 100644 index 0000000..5dc2038 --- /dev/null +++ b/props/ice/cpf.f90 @@ -0,0 +1,113 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in J/kg/K) +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return cpf [J/kg/K] +!> @details +!> cpf(i,j,k,ismpl) calculates the isobaric heat capacity in (in J/kg/K)\n +!> of pure water, given temperature (t, in C), and pressure (p,in Pa)\n +!> at node(i,j,k).\n +!> method: c_p = d/dT E, E= fluid enthaply.\n +!> derived from the formulation given in:\n +!> zylkovskij et al: models and methods summary for\n +!> the fehmn application,\n +!> ecd 22, la-ur-94-3787, los alamos nl, 1994.\n +!> Speedy, R.J. (1987) Thermodynamic properties of supercooled water \n +!> at 1 atm. Journal of Physical Chemistry, 91: 3354–3358. \n +!> range of validity:\n +!> pressures 0.01 - 110 MPa,\n +!> temperature 0.001 - 350 °c\n +!> input:\n +!> pressure plocal [Pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION cpf(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION plocal, tlocal, enth, denthdt, tred, p, p1, & + p2, p3, p4, t, t1, t2, t3, tp, t2p, tp2, ta, tb, da, db, b2 + DOUBLE PRECISION cf(20), bf(6) + DATA cf/0.25623465D-3, 0.10184405D-2, 0.22554970D-4, & + 0.34836663D-7, 0.41769866D-2, -0.21244879D-4, 0.25493516D-7, & + 0.89557885D-4, 0.10855046D-6, -0.21720560D-6, 0.10000000D+1, & + 0.23513278D-1, 0.48716386D-4, -0.19935046D-8, & + -0.50770309D-2, 0.57780287D-5, 0.90972916D-9, & + -0.58981537D-4, -0.12990752D-7, 0.45872518D-8/ + +! new: after Speedy (1987) for T < 0 to -46 C + DATA bf/14.2D0, 25.952D0, 128.281D0, -221.405D0, 196.894D0, & + -64.812D0/ +! end new + + + plocal = pres(i,j,k,ismpl)*pa_conv1 + tlocal = temp(i,j,k,ismpl) + IF (tlocal<-45D0) tlocal = -45.D0 + + IF (tlocal<0.D0) THEN +! new: after Speedy (1987) for T < 0 to -46 C + tred = (tlocal+273.15D0-227.15D0)/227.15D0 + cpf = bf(1)/sqrt(tred) + bf(2) + bf(3)*tred + & + bf(4)*tred*tred + bf(5)*tred*tred*tred + & + bf(6)*tred*tred*tred*tred + cpf = cpf*0.99048992406520D0*1000.D0/18.D0 + ELSE +! end new + IF (tlocal>300.D0) tlocal = 300.D0 + + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + t2p = t2*p + tp2 = t*p2 +! enthalpy + ta = cf(1) + cf(2)*p + cf(3)*p2 + cf(4)*p3 + cf(5)*t + & + cf(6)*t2 + cf(7)*t3 + cf(8)*tp + cf(10)*t2p + cf(9)*tp2 + tb = cf(11) + cf(12)*p + cf(13)*p2 + cf(14)*p3 + cf(15)*t + & + cf(16)*t2 + cf(17)*t3 + cf(18)*tp + cf(20)*t2p + & + cf(19)*tp2 + enth = ta/tb + +! derivative + da = cf(5) + 2.D0*cf(6)*t + 3.D0*cf(7)*t2 + cf(8)*p + & + 2.D0*cf(10)*tp + cf(9)*p2 + db = cf(15) + 2.D0*cf(16)*t + 3D0*cf(17)*t2 + cf(18)*p + & + 2.D0*cf(20)*tp + cf(19)*p2 + + b2 = tb*tb + denthdt = da/tb - ta*db/b2 + cpf = denthdt*1.D6 + END IF + + RETURN + END diff --git a/props/ice/cpi.f90 b/props/ice/cpi.f90 new file mode 100644 index 0000000..5dc9c56 --- /dev/null +++ b/props/ice/cpi.f90 @@ -0,0 +1,66 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculate ice isobaric heat capacity [J/(kg*K)] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @details +!> After: +!> Ling, F. & Zhang (2004): +!> A Numerical Modelfor surface energy balance and the thermal +!> regime of the active layer and permafrost containing +!> unfrozen water or brine +!> Cold Regions Science & Technology, 38, 1-15 +!> Ling and Zhang cite Osterkamp, T. E. (1987): +!> Freezing and Thawing of Soils and Permafrost +!> Containing Unfrozen Water or Brine +!> Water Resources Research, Vol. 23, No. 12, pages 2279-2285 +!> Osterkamp cites Dorsey, N. E. (1940): +!> Properties of Ordinary Water-Substance, Reinhold, New York +!> Dorsey cites Dickinson, H., & Osborne, N. (1915): +!> The specific heat and heat of fusion of ice. Journal of +!> the Washington Academy of Sciences, 5(10), 338-340. +!> +!> Alternative: +!> Fukusako, S.: +!> Thermophysical Properties of Ice, Snow,and Sea Ice +!> International Journal of Thermophysics, 1990, 11, 353-372 + DOUBLE PRECISION FUNCTION cpi(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION plocal, tlocal + + tlocal = temp(i,j,k,ismpl) + IF (tlocal>0.D0) tlocal = 0.D0 + +!vr (Fukosako 1990) cpi = 185.D0 + 6.89D0*(273.15D0+tlocal) + cpi=2110.D0+7.7D0*tlocal + + RETURN + END diff --git a/props/ice/disp.f90 b/props/ice/disp.f90 new file mode 100644 index 0000000..fec0e92 --- /dev/null +++ b/props/ice/disp.f90 @@ -0,0 +1,40 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief assign effective diffusivity z direction to cell +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!#> @return disp effective diffusivity z direction + DOUBLE PRECISION FUNCTION disp(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + INTEGER i, j, k, ismpl + + disp = propunit(uindex(i,j,k),idx_df,ismpl) + + RETURN + END diff --git a/props/ice/ftheta.f90 b/props/ice/ftheta.f90 new file mode 100644 index 0000000..fcd83d0 --- /dev/null +++ b/props/ice/ftheta.f90 @@ -0,0 +1,139 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates the fluid/ice partition function +!> @param[in] tlocal = temperature +!> @param[in] tliq = phase boundary temperature +!> @param[in] wmushy = scaling factor for "mushy" region = Tsolidus-tliqidus +!> @param[in] ismpl local sample index +!> @param[out] theta = value of partition function (0<Theta<1) +!> @param[out] dtheta = value of derivative of partition function with respect to temperature +!#> returns the fluid/ice partition function theta and its derivative dtheta +!> @details +!>calculates the fluid/ice partition function used for the \n +!>apparent heat capacity approach to phase change.\n + SUBROUTINE ftheta(tlocal,tliq,wmushy,theta,dtheta,ismpl) + use arrays + use ice + IMPLICIT NONE + INTEGER ismpl + DOUBLE PRECISION tlocal, theta, dtheta, val, tliq, wmushy + + theta = 1.D0 + dtheta = 0.D0 + + IF (tlocal<tliq) THEN + val = (tlocal-tliq)/wmushy +! Theta=exp((-(T-Tf)/w)^2) + theta = exp(-val*val) +! dTheta=-2*(T-Tf)/w^2*Theta; + dtheta = -2.D0*val*theta/wmushy +! IF (theta.lt.liqmin) THEN +! theta = liqmin +! dtheta = 0. +! END IF + + END IF + RETURN + END + + +!> @brief calculates the fluid/ice partition function used for the +!> @param[in] tlocal = temperature +!> @param[in] tliq = phase boundary temperature +!> @param[in] wmushy = scaling factor for "mushy" region = tsolidus-tliqidus +!> @param[in] ismpl local sample index +!> @param[out] theta = value of partition function (0<Theta<1) +!> @param[out] dtheta = value of derivative of partition function with respect to temperature +!> @details +!>calculates the fluid/ice partition function used for the \n +!>apparent heat capacity approach to phase change (galushkin)\n + SUBROUTINE ftheta_gal(tlocal,tliq,wmushy,theta,dtheta,ismpl) + use arrays + use ice + IMPLICIT NONE + INTEGER ismpl + DOUBLE PRECISION solid, tlocal, tref, tlimit, km, theta, & + dtheta, a0, a1, a2, a3, a4, a5, a6, a7, a8, tliq, wmushy + DOUBLE PRECISION t, t1, t2, t3, t4, t5, t6, t7, t8 + PARAMETER (a0=1.0D0,a1=0.60152823763179D0, & + a2=0.23218232347212D0,a3=0.04669792788297D0, & + a4=0.00535597924776D0,a5=0.00036415588418D0, & + a6=0.00001450956751D0,a7=0.00000031279149D0, & + a8=0.00000000281502D0) + + theta = 1.D0 + dtheta = 0.0 + + IF (tlocal<tliq) THEN + t1 = tlocal + t2 = t1*t1 + t3 = t2*t1 + t4 = t3*t1 + t5 = t4*t1 + t6 = t5*t1 + t7 = t6*t1 + t8 = t7*t1 + theta = a0 + a1*t1 + a2*t2 + a3*t3 + a4*t4 + a5*t5 + a6*t6 + & + a7*t7 + a8*t8 + dtheta = a1 + 2.D0*a2*t1 + 3.D0*a3*t2 + 4.D0*a4*t3 + & + 5.D0*a5*t4 + 6.D0*a6*t5 + 7.D0*a7*t6 + 8.D0*a8*t7 + END IF + RETURN + END + +!> @brief calculates the fluid/ice partition function used for the +!> @param[in] tlocal = temperature +!> @param[in] tliq = phase boundary temperature +!> @param[in] wpara = scaling factor for "mushy" region = tsolidus-tliqidus +!> @param[in] ismpl local sample index +!> @param[out] theta = value of partition function (0<Theta<1) +!> @param[out] dtheta = value of derivative of partition function with respect to temperature +!> @details +!>calculates the fluid/ice partition function used for the \n +!>apparent heat capacity approach to phase change (nikolsky2009)\n + SUBROUTINE ftheta_nik(tlocal,tliq,wpara,theta,dtheta,ismpl) + use arrays + use ice + IMPLICIT NONE + INTEGER ismpl + DOUBLE PRECISION solid,tlocal,tref,tlimit,km,theta,dtheta + DOUBLE PRECISION tliq,wpara + + theta = 1.d0 + dtheta = 0.0d0 + + IF (tlocal<tliq .and. wpara>=0.5d0 .and. wpara<=0.8d0) THEN + theta = (abs(tliq)**wpara)*(abs(tlocal)**(-wpara)) + +!AW + dtheta= (abs(tliq)**wpara)* & + (-wpara)*abs(tlocal)**(-wpara-1.d0) +!AW oben stehende Zwischenloesung muss mit unten stehendem Original korrigiert werden <- SIGN ist aber falsch!!! + WRITE(*,*) 'error: "ftheta_nik" needs to be modified!!!' + STOP +!AW-original dtheta= (abs(tliq)**wpara)* & +!AW-original (-wpara)*abs(tlocal)**(-wpara-1.d0)*sign(tlocal) + + END IF + RETURN + END diff --git a/props/ice/ice.f90 b/props/ice/ice.f90 new file mode 100644 index 0000000..02d7fdf --- /dev/null +++ b/props/ice/ice.f90 @@ -0,0 +1,33 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief variables for permafrost +! icefrac +! liq liquidus temperature in degree Celsius (above which ice is molten) +! sol solidus temperature in degree Celsius (below which water is frozen) +! lth latent heat of water and ice in J / kg +!> liqmin NOT USED: minimal value of fluid/ice partition function theta i [-] + MODULE ice + DOUBLE PRECISION, ALLOCATABLE :: icefrac(:,:,:) + DOUBLE PRECISION, ALLOCATABLE :: liq(:,:,:), sol(:,:,:) + DOUBLE PRECISION lth, liqmin + END MODULE ice diff --git a/props/ice/ice.inc b/props/ice/ice.inc new file mode 100644 index 0000000..97f58f1 --- /dev/null +++ b/props/ice/ice.inc @@ -0,0 +1,23 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + use ice diff --git a/props/ice/ice_allocate.f90 b/props/ice/ice_allocate.f90 new file mode 100644 index 0000000..96319ab --- /dev/null +++ b/props/ice/ice_allocate.f90 @@ -0,0 +1,57 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!#> @brief allocates space for variables for permafrost +! icefrac +! liq liquidus temperature in degree Celsius (above which ice is molten) +! sol solidus temperature in degree Celsius (below which water is frozen) +! i0 number of cells in x direction +! j0 number of cells in y direction +! k0 number of cells in z direction + SUBROUTINE ice_allocate + use ice + use mod_genrl + IMPLICIT NONE + + ALLOCATE(icefrac(i0,j0,k0)) + ALLOCATE(liq(i0,j0,k0)) + ALLOCATE(sol(i0,j0,k0)) + + RETURN + END + +!#> @brief deallocates space for +! icefrac +! liq liquidus temperature in degree Celsius (above which ice is molten) +! sol solidus temperature in degree Celsius (below which water is frozen) + + SUBROUTINE ice_deallocate + use ice + IMPLICIT NONE + + DEALLOCATE(icefrac) + DEALLOCATE(liq) + DEALLOCATE(sol) + + RETURN + END diff --git a/props/ice/kx.f90 b/props/ice/kx.f90 new file mode 100644 index 0000000..cf4a635 --- /dev/null +++ b/props/ice/kx.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief assign permeability in x direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) + DOUBLE PRECISION FUNCTION kx(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION t0, theta, dtheta, w0, tlocal, permi, ff, fi, & + porlocal, por + EXTERNAL por + + tlocal = temp(i,j,k,ismpl) + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + porlocal = por(i,j,k,ismpl) + ff = porlocal*theta + fi = porlocal - ff + permi = 10.D0**(-100.D0*fi/(porlocal+1.D-12)) + + IF (permi<1.0D-6) THEN + + permi = 1.0D-6 + + END IF + +! permeff=PERM(I,J,K)*permi + kx = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_kx,ismpl)*permi + + RETURN + END diff --git a/props/ice/ky.f90 b/props/ice/ky.f90 new file mode 100644 index 0000000..0f61e2e --- /dev/null +++ b/props/ice/ky.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief assign permeability in y direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) + DOUBLE PRECISION FUNCTION ky(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION t0, theta, dtheta, w0, tlocal, permi, ff, fi, & + porlocal, por + EXTERNAL por + + tlocal = temp(i,j,k,ismpl) + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + porlocal = por(i,j,k,ismpl) + ff = porlocal*theta + fi = porlocal - ff + permi = 10.D0**(-100.D0*fi/(porlocal+1.D-12)) + + IF (permi<1.0D-6) THEN + + permi = 1.0D-6 + + END IF + +! permeff=PERM(I,J,K)*permi + ky = propunit(uindex(i,j,k),idx_kz,ismpl)* & + propunit(uindex(i,j,k),idx_an_ky,ismpl)*permi + + RETURN + END diff --git a/props/ice/kz.f90 b/props/ice/kz.f90 new file mode 100644 index 0000000..7b9aa35 --- /dev/null +++ b/props/ice/kz.f90 @@ -0,0 +1,63 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief assign permeability in z direction to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return permeability (m^2) +!> @details + DOUBLE PRECISION FUNCTION kz(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION t0, theta, dtheta, w0, tlocal, permi, ff, fi, & + porlocal, por + EXTERNAL por + + tlocal = temp(i,j,k,ismpl) + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + porlocal = por(i,j,k,ismpl) + ff = porlocal*theta + fi = porlocal - ff + permi = 10.D0**(-100.D0*fi/(porlocal+1.D-12)) + + IF (permi<1.0D-6) THEN + + permi = 1.0D-6 + + END IF + +! permeff=PERM(I,J,K)*permi + kz = propunit(uindex(i,j,k),idx_kz,ismpl)*permi + + RETURN + END diff --git a/props/ice/lamf.f90 b/props/ice/lamf.f90 new file mode 100644 index 0000000..89fd5c2 --- /dev/null +++ b/props/ice/lamf.f90 @@ -0,0 +1,62 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculate the thermal conductivity lamf in W/(m*K) of the formation water +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lamf[W/(m*K)] +!> @details +!> calculate the thermal conductivity lamf in W/(m*K) of\n +!>formation water, given temperature in C, and salinity in mass fraction\n +!>(g/g)of NaCl. Thermal conductivity of freshwater, lamfw is calculated using\n +!>the Phillips (1981) formulation. \n +!> Phillips, S. L. "A technical databook for geothermal energy utilization."(1981). +!>Range of validity: 20 to 330�C and up to 4 molal NaCl\n +!> input:\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION lamf(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION tlocal, tr, tr2, tr3, tr4 + + + tlocal = temp(i,j,k,ismpl) + IF (tlocal<0.D0) tlocal = 0.D0 + IF (tlocal>300.D0) tlocal = 300.D0 + + tr = (tlocal+273.15D0)/273.15D0 + tr2 = tr*tr + tr3 = tr2*tr + tr4 = tr3*tr + lamf = (-0.92247D0+2.8395D0*tr-1.8007D0*tr2+0.52577D0*tr3- & + 0.07344D0*tr4) + + RETURN + END diff --git a/props/ice/lami.f90 b/props/ice/lami.f90 new file mode 100644 index 0000000..a5985fc --- /dev/null +++ b/props/ice/lami.f90 @@ -0,0 +1,61 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate ice thermal conductivity [W/(m*K)] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!#> return thermal conductivity of ice [W/(m*K)] +!> @details +!> Ling, F. & Zhang, T. (2004): +!> A Numerical Modelfor surface energy balance and the thermal +!> regime of the active layer and permafrost containing +!> unfrozen water or brine +!> Cold Regions Science & Technology, 38, 1-15 +!> Ling and Zhang cite Osterkamp, T. E. (1987): +!> Freezing and Thawing of Soils and Permafrost +!> Containing Unfrozen Water or Brine +!> Water Resources Research, Vol. 23, No. 12, pages 2279-2285 +!> Alternative: +!> Fukusako, S.: +!> Thermophysical Properties of Ice, Snow,and Sea Ice +!> International Journal of Thermophysics, 1990, 11, 353-372 + DOUBLE PRECISION FUNCTION lami(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION plocal, tlocal + + tlocal = temp(i,j,k,ismpl) + IF (tlocal>0.D0) tlocal = 0.D0 + lami = 0.4685D0 + 488.19D0/(tlocal+273.16D0) + +! vr (Fukosako1990) +! vr lami=1.16d0*(1.91d0-8.66d-3*tlocal+2.97d-5*tlocal*tlocal); + + + RETURN + END diff --git a/props/ice/lamm.f90 b/props/ice/lamm.f90 new file mode 100644 index 0000000..4b50486 --- /dev/null +++ b/props/ice/lamm.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate temperature dependent thermal conductivity +!> @param[in,out] solid thermal conductivity at reference temperature given in input file [W / (m K)] +!> @param[in,out] tlocal temperature at this sample index [degree Celsius] +!> @param[in,out] tref reference temperature [degree Celsius] +!> @param[in] ismpl local sample index +!> @return thermal conductivity [W / (m K)] +!> @details +!> calculate temperature dependent thermal conductivity of the stony matrix\n +!> (zoth & haenel, 1988)\n + DOUBLE PRECISION FUNCTION lamm(solid,tlocal,tref,ismpl) + + + IMPLICIT NONE + + INTEGER ismpl + DOUBLE PRECISION solid, tlocal, tref, tlimit + DOUBLE PRECISION cddz, cddz0, cgt0, wgt, cgt + PARAMETER (tlimit=800.D0) + + IF (tlocal>tlimit) THEN + lamm = 770.0D0/(350.0D0+tlocal) + 0.7D0 + ELSE + cddz = 770.0D0/(350.0D0+tlocal) + 0.7D0 + cddz0 = 770.0D0/(350.0D0+tref) + 0.7D0 + cgt0 = solid/cddz0 + wgt = (tlocal-tref)/(tlimit-tref) + cgt = cgt0 - (cgt0-1.0D0)*wgt + lamm = cgt*cddz + END IF + + RETURN + END diff --git a/props/ice/lx.f90 b/props/ice/lx.f90 new file mode 100644 index 0000000..5054335 --- /dev/null +++ b/props/ice/lx.f90 @@ -0,0 +1,76 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lx[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION lx(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION tlocal, lsolid, lfluid, porlocal, fm, fi, ff + DOUBLE PRECISION t0, theta, dtheta, w0, lice + DOUBLE PRECISION lamm, lamf, lami, por + EXTERNAL lamf, lamm, lami, por + + ui = uindex(i,j,k) + tlocal = temp(i,j,k,ismpl) + + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + + lfluid = lamf(i,j,k,ismpl) + lice = lami(i,j,k,ismpl) + + lsolid = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_lx,ismpl & + ) + lsolid = lamm(lsolid,tlocal,tref,ismpl) + + porlocal = por(i,j,k,ismpl) + fm = 1.D0 - porlocal + ff = porlocal*theta + fi = porlocal - ff + + + + lx = lsolid**fm*lfluid**ff*lice**fi + + RETURN + END diff --git a/props/ice/ly.f90 b/props/ice/ly.f90 new file mode 100644 index 0000000..146801c --- /dev/null +++ b/props/ice/ly.f90 @@ -0,0 +1,75 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity ly[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION ly(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION tlocal, lsolid, lfluid, porlocal, fm, fi, ff + DOUBLE PRECISION t0, theta, dtheta, w0, lice + DOUBLE PRECISION lamm, lamf, lami, por + EXTERNAL lamf, lamm, lami, por + + ui = uindex(i,j,k) + tlocal = temp(i,j,k,ismpl) + + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + + lfluid = lamf(i,j,k,ismpl) + lice = lami(i,j,k,ismpl) + + lsolid = propunit(ui,idx_lz,ismpl)*propunit(ui,idx_an_ly,ismpl & + ) + lsolid = lamm(lsolid,tlocal,tref,ismpl) + + porlocal = por(i,j,k,ismpl) + fm = 1.D0 - porlocal + ff = porlocal*theta + fi = porlocal - ff + + + ly = lsolid**fm*lfluid**ff*lice**fi + + RETURN + END diff --git a/props/ice/lz.f90 b/props/ice/lz.f90 new file mode 100644 index 0000000..bcc91f7 --- /dev/null +++ b/props/ice/lz.f90 @@ -0,0 +1,74 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION lz(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION tlocal, lsolid, lfluid, porlocal, fm, fi, ff + DOUBLE PRECISION t0, theta, dtheta, w0, lice + DOUBLE PRECISION lamm, lamf, lami, por + EXTERNAL lamf, lamm, lami, por + + ui = uindex(i,j,k) + tlocal = temp(i,j,k,ismpl) + + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + + lfluid = lamf(i,j,k,ismpl) + lice = lami(i,j,k,ismpl) + + lsolid = propunit(ui,idx_lz,ismpl) + lsolid = lamm(lsolid,tlocal,tref,ismpl) + + porlocal = por(i,j,k,ismpl) + fm = 1.D0 - porlocal + ff = porlocal*theta + fi = porlocal - ff + + + lz = lsolid**fm*lfluid**ff*lice**fi + + RETURN + END diff --git a/props/ice/por.f90 b/props/ice/por.f90 new file mode 100644 index 0000000..44fce21 --- /dev/null +++ b/props/ice/por.f90 @@ -0,0 +1,41 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief assign porosity to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return porosity porlocal [-] + DOUBLE PRECISION FUNCTION por(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ismpl + + por = propunit(uindex(i,j,k),idx_por,ismpl) + + RETURN + END diff --git a/props/ice/props_check.f90 b/props/ice/props_check.f90 new file mode 100644 index 0000000..4218ff9 --- /dev/null +++ b/props/ice/props_check.f90 @@ -0,0 +1,56 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief check current PROPS choice +!> @param[in] ismpl local sample index + SUBROUTINE props_check(ismpl) + + + use mod_genrlc + IMPLICIT NONE + INTEGER ismpl + character (len=10) :: ldef_props + PARAMETER (ldef_props='ice') + LOGICAL test_option + EXTERNAL test_option + INTRINSIC trim + + +#ifndef PROPS_ice + WRITE(*,'(3A)') 'error: this source was written for PROPS=', & + ldef_props, & + ', please correct this check in "props_check.f"!' + STOP +#endif + IF ( .NOT. test_option('PROPS='//trim(def_props))) THEN + IF (ldef_props/=def_props) THEN + WRITE(*,'(7A)') 'error: model file needs an executable', & + ' build from PROPS=', trim(def_props), & + ', but the current', ' consist of PROPS=', & + trim(ldef_props), '!' + STOP + END IF + END IF + + RETURN + END diff --git a/props/ice/props_init.f90 b/props/ice/props_init.f90 new file mode 100644 index 0000000..5dd532d --- /dev/null +++ b/props/ice/props_init.f90 @@ -0,0 +1,81 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief init routine +!> @param[in] ismpl local sample index +!> @details +!> Set the following module variables \n +!> - icefraq \n +!> - liq liquidus temperature in degree Celsius \n +!> - sol solidus temperature in degree Celsius \n +!> - lth latent heat in J / kg \n +!> - liqmin minimal value of fluid/ice partition function theta in [-] \n +!> +!> Use the following module variables \n +!> - i0 number of cells in x direction \n +!> - j0 number of cells in y direction \n +!> - k0 number of cells in z direction \n + SUBROUTINE props_init(ismpl) + use arrays + use ice + use mod_genrl + use mod_time + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + + IF (linfos(3)>=2) WRITE(*,*) & + ' ... permafrost properties used' + + CALL ice_allocate + + CALL read_props(ismpl) + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + icefrac(i,j,k) = 0.D0 + liq(i,j,k) = 0.D0 + sol(i,j,k) = -2.D0 + END DO + END DO + END DO + + lth = 333600.0D0 + liqmin = 0.03D0 + + CALL check_props(ismpl) + + RETURN + END + +!> @brief dummy +!> @param[in] ismpl local sample index +!> calls ice_deallocate + SUBROUTINE props_end(ismpl) + IMPLICIT NONE + INTEGER ismpl + + CALL ice_deallocate + RETURN + END diff --git a/props/ice/qc.f90 b/props/ice/qc.f90 new file mode 100644 index 0000000..c7ee133 --- /dev/null +++ b/props/ice/qc.f90 @@ -0,0 +1,39 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign transport production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] spec species index +!> @param[in] ismpl local sample index +!> @return transport production + DOUBLE PRECISION FUNCTION qc(i,j,k,spec,ismpl) + use arrays + IMPLICIT NONE + INTEGER i, j, k, ismpl, spec + + + qc = 0.D0 + + RETURN + END diff --git a/props/ice/qf.f90 b/props/ice/qf.f90 new file mode 100644 index 0000000..83b46d1 --- /dev/null +++ b/props/ice/qf.f90 @@ -0,0 +1,38 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign flow production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return flow production + DOUBLE PRECISION FUNCTION qf(i,j,k,ismpl) + use arrays + IMPLICIT NONE + INTEGER i, j, k, ismpl + + + qf = 0.D0 + + RETURN + END diff --git a/props/ice/qt.f90 b/props/ice/qt.f90 new file mode 100644 index 0000000..9245a71 --- /dev/null +++ b/props/ice/qt.f90 @@ -0,0 +1,43 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief assign heat production to cell +!> @param[in] i grid indices +!> @param[in] j grid indices +!> @param[in] k grid indices +!> @param[in] ismpl local sample index +!> @return heat production [W / m^3] + DOUBLE PRECISION FUNCTION qt(i,j,k,ismpl) + use arrays + IMPLICIT NONE + INTEGER i, j, k, ismpl + DOUBLE PRECISION por + + +! vr : aCtor (1-por) ? +! por=propunit(uindex(i,j,k),idx_por,ismpl) +! qt = (1.d0- por)*(propunit(uindex(i,j,k),idx_q,ismpl) + + qt = propunit(uindex(i,j,k),idx_q,ismpl) + + RETURN + END diff --git a/props/ice/rce.f90 b/props/ice/rce.f90 new file mode 100644 index 0000000..b579754 --- /dev/null +++ b/props/ice/rce.f90 @@ -0,0 +1,74 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates effective thermal conductivity of the two phase +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return thermal conductivity lz[W/(m*K)] +!> @details +!> calculates effective thermal conductivity of the two phase\n +!> system matrix-porosity .\n +!> input:\n +!> porosity porlocal [-]\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION rhoceff(i,j,k,ismpl) + + + use arrays + use ice + use mod_temp + IMPLICIT NONE + + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION tlocal, rcsolid, rcfluid, rcice, porlocal, & + fm, fi, ff + DOUBLE PRECISION t0, theta, dtheta, w0 + DOUBLE PRECISION rhocm, rhocf, rhoci, por, rhoi, rhof + EXTERNAL rhocf, rhocm, rhoci, por, rhoi, rhof + + ui = uindex(i,j,k) + tlocal = temp(i,j,k,ismpl) + t0 = liq(i,j,k) + w0 = abs(liq(i,j,k)-sol(i,j,k))/2.D0 + CALL ftheta(tlocal,t0,w0,theta,dtheta,ismpl) + + rcfluid = rhocf(i,j,k,ismpl) + rcice = rhoci(i,j,k,ismpl) + rcsolid = rhocm(i,j,k,ismpl) + + porlocal = por(i,j,k,ismpl) + + fm = 1.D0 - porlocal + ff = porlocal*theta + fi = porlocal - ff + +!DM Korrektur, 2008/02/21 + rhoceff = rcsolid*fm + rcfluid*ff + rcice*fi + & + rhof(i,j,k,ismpl)*porlocal*lth*dtheta + + RETURN + END diff --git a/props/ice/read_props.f90 b/props/ice/read_props.f90 new file mode 100644 index 0000000..3da2600 --- /dev/null +++ b/props/ice/read_props.f90 @@ -0,0 +1,86 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief read user defined additionally parameter +!> @param[in] ismpl local sample index + SUBROUTINE read_props(ismpl) + + + use arrays + use ice + use mod_genrl + use mod_genrlc + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + + character (len=80) :: line + + INTEGER lblank + LOGICAL found, no_ext_link + EXTERNAL found, no_ext_link, lblank + + + +! PLEASE comment out the following line if you want to use the additional reading + RETURN + +! std. screen information + WRITE(*,*) + WRITE(*,*) ' reading additionally user parameter:' + WRITE(*,*) ' from file "', project(:lblank(project)), '"' +! open model file + OPEN(79,file=project,status='old') +! init HDF5 support, when available + CALL open_hdf5(' ') + +! --------- begin reading part --------- + +! !!! [liq] reading example for an existing [I0,J0,K0] array + +! searching for the right data part, special keyword '# liq init' + IF (found(79,'# liq init',line,.FALSE.)) THEN +! check for an HDF5 entry 'liq', if available read the array [liq] from the HDF5 file + IF (no_ext_link(i0,j0,k0,liq,'liq',line)) THEN +! read the values from the model file instead of the HDF5 file + READ(79,*) (((liq(i,j,k),i=1,i0),j=1,j0),k=1,k0) + END IF +! std. screen information + WRITE(*,*) ' [R] : liq' + ELSE +! std. screen information, when '# liq init' not found + WRITE(*,*) ' <D> : liq = -0.04' +! make a default initialisation of the array [liq] with '-0.04d0' + CALL set_dval(i0*j0*k0,-0.04D0,liq) + END IF + +! !!! add here additionally array readings ... + +! --------- begin reading part --------- + +! finish HDF5 support + CALL close_hdf5() +! close model file + CLOSE(79) + RETURN + END diff --git a/props/ice/rhocf.f90 b/props/ice/rhocf.f90 new file mode 100644 index 0000000..7e05517 --- /dev/null +++ b/props/ice/rhocf.f90 @@ -0,0 +1,53 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates heat capacity times density of water. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhocf rhocf[J / (m^3 * K)] +!> @details +!> input:\n +!> heat capacity of water cpf [J / kg / K]\n +!> density rhof [kg/m^3]\n +!> pressure plocal [Pa]\n +!> temperature tlocal [C]\n + DOUBLE PRECISION FUNCTION rhocf(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION plocal, tlocal, rfluid, cfluid, cpf, rhof + EXTERNAL cpf, rhof + +! water density [kg/m**3] + rfluid = rhof(i,j,k,ismpl) +! water isobariC heat CapaCity [J/(kg*K)] + cfluid = cpf(i,j,k,ismpl) + rhocf = rfluid*cfluid + + RETURN + END diff --git a/props/ice/rhoci.f90 b/props/ice/rhoci.f90 new file mode 100644 index 0000000..d62a398 --- /dev/null +++ b/props/ice/rhoci.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculates heat capacity*density of ice . +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhoci rc[J / (m^3 * K)] +!> @details +!> input:\n +!> heat capacity of ice cpi [J / kg / K]\n +!> density rhoi [kg/m^3]\n +!> temperature tlocal [C]\n + DOUBLE PRECISION FUNCTION rhoci(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION tlocal, rhoi, cpi + EXTERNAL rhoi, cpi + + tlocal = temp(i,j,k,ismpl) + IF (tlocal>0.D0) tlocal = 0.D0 + + rhoci = rhoi(i,j,k,ismpl)*cpi(i,j,k,ismpl) + + RETURN + END diff --git a/props/ice/rhocm.f90 b/props/ice/rhocm.f90 new file mode 100644 index 0000000..eb16b07 --- /dev/null +++ b/props/ice/rhocm.f90 @@ -0,0 +1,49 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + + +!> @brief calculates product of heat capacity and density of rock. +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhocm rc [J / (m^3 K)] +!> @details +!> input:\n +!> pressure plocal [Mpa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION rhocm(i,j,k,ismpl) + + + use arrays + use mod_temp + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION plocal, tlocal + + tlocal = temp(i,j,k,ismpl) + rhocm = propunit(uindex(i,j,k),idx_rc,ismpl)* & + (cma1+cma2*tlocal+cma3*tlocal*tlocal) + + RETURN + END diff --git a/props/ice/rhof.f90 b/props/ice/rhof.f90 new file mode 100644 index 0000000..a8e44bb --- /dev/null +++ b/props/ice/rhof.f90 @@ -0,0 +1,104 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure water, +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return rhof [kg/m^3] +!> @details +!> rhof(i,j,k,ismpl) calculates the density in (in kg/m^3) of pure water,\n +!> given temperature (t, in c), and pressure (p,in Mpa) at node(i,j,k)\n +!> derived from the formulation given in:\n +!> zylkovskij et al: models and methods summary for\n +!> the fehmn application,\n +!> ecd 22, la-ur-94-3787, los alamos nl, 1994.\n +!> Speedy, R.J. (1987) Thermodynamic properties of supercooled water\n +!> at 1 atm. Journal of Physical Chemistry, 91: 3354–3358. +!> range of validity:\n +!> pressures 0.01 - 110 MPa,\n +!> temperature 15 - 350 °C\n +!> input:\n +!> pressure plocal [Pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION rhof(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION cf(20), bf(6) + DOUBLE PRECISION ta, tb, tlocal, plocal, t, t2, t3, tred, p, & + p2, p3, p4, tp, t2p, tp2, contfac + + DATA cf/0.10000000D+01, 0.17472599D-01, -0.20443098D-04, & + -0.17442012D-06, 0.49564109D-02, -0.40757664D-04, & + 0.50676664D-07, 0.50330978D-04, 0.33914814D-06, & + -0.18383009D-06, 0.10009476D-02, 0.16812589D-04, & + -0.24582622D-07, -0.17014984D-09, 0.48841156D-05, & + -0.32967985D-07, 0.28619380D-10, 0.53249055D-07, & + 0.30456698D-09, -0.12221899D-09/ +! new: after Speedy (1987) for T < 0 to -46 C (see also Grant, S. A., Physical \n +! and Chemical Factors Affecting Contaminant Hydrology in Cold Environments, \n +! Technical Report ERDC/CRREL TR-00-21, US Army Corps of Engineers, 2000) \n + DATA bf/901.5328593D0, -0.0011761652D0, 0.0038442382D0, & + -0.0157270761D0, 0.0744064614D0, -0.1406432653D0/ +! end new + + contfac = 0.999195706402050D0 + plocal = pres(i,j,k,ismpl)*pa_conv1 + tlocal = temp(i,j,k,ismpl) + IF (tlocal<-45.D0) tlocal = -45.D0 + + IF (tlocal<0.D0) THEN +! new: after Speedy (1987) for T < 0 to -46 C + tred = (tlocal+273.15D0-227.15D0)/227.15D0 + rhof = contfac*bf(1)*exp(-227.15D0*(bf(3)*tred+0.5D0*bf(4)* & + tred*tred+0.333D0*bf(5)*tred*tred*tred+0.25D0*bf( & + 6)*tred*tred*tred*tred+2.D0*bf(2)*sqrt(tred))) + ELSE +! end new + IF (tlocal>300.D0) tlocal = 300.D0 + + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + t2p = t2*p + tp2 = t*p2 + +! liquid density + ta = cf(1) + cf(2)*p + cf(3)*p2 + cf(4)*p3 + cf(5)*t + & + cf(6)*t2 + cf(7)*t3 + cf(8)*tp + cf(10)*t2p + cf(9)*tp2 + tb = cf(11) + cf(12)*p + cf(13)*p2 + cf(14)*p3 + cf(15)*t + & + cf(16)*t2 + cf(17)*t3 + cf(18)*tp + cf(20)*t2p + & + cf(19)*tp2 + rhof = ta/tb + END IF + + RETURN + END diff --git a/props/ice/rhoi.f90 b/props/ice/rhoi.f90 new file mode 100644 index 0000000..d1debe7 --- /dev/null +++ b/props/ice/rhoi.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief calculate ice density [kg/m^3] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @details +!> Fukusako, S.: +!> Thermophysical Properties of Ice, Snow,and Sea Ice +!> International Journal of Thermophysics, 1990, 11, 353-372 +!> +!> There should be another source. + DOUBLE PRECISION FUNCTION rhoi(i,j,k,ismpl) + + + use arrays + IMPLICIT NONE + + INTEGER i, j, k, ui, ismpl + DOUBLE PRECISION plocal, tlocal + + + tlocal = temp(i,j,k,ismpl) + IF (tlocal>0.D0) tlocal = 0.D0 + + rhoi = 917.D0 - 0.151D0*tlocal + + RETURN + END diff --git a/props/ice/rhow.f90 b/props/ice/rhow.f90 new file mode 100644 index 0000000..245212c --- /dev/null +++ b/props/ice/rhow.f90 @@ -0,0 +1,134 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!#> @brief <description> +!#> @param[in] p <description> +!#> @param[in] t <description> +!#> @param[in] ismpl local sample index +!#> @return rho <description> +!#> @details + DOUBLE PRECISION FUNCTION rhow(p,t) + IMPLICIT NONE + DOUBLE PRECISION t, p, p2, t2, t4, t6 + DOUBLE PRECISION a, b, c, d, e, f, g + DOUBLE PRECISION a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, & + d2, e0, e1, e2, f0, f1, f2, g0, g1, g2 + DATA a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2, e0, e1, & + e2, f0, f1, f2, g0, g1, g2/ + 9.99792877961606D+02, & + + 5.07605113140940D-04, -5.2842547816413D-10, & + + 5.13864847162196D-02, -3.61991396354483D-06, & + + 7.97204102509724D-12, -7.53557031774437D-03, & + + 6.37212093275576D-05, -1.66203631393248D-13, & + + 4.60380647957350D-05, -5.61299059722121D-10, & + + 1.80924436489400D-15, -2.26651454175013D-07, & + + 3.36874416675978D-12, -1.30352149261326D-17, & + + 6.14889851856743D-10, -1.06165223196756D-14, & + + 4.75014903737416D-20, -7.39221950969522D-13, & + + 1.42790422913922D-17, -7.13130230531541D-23/ + + + p2 = p*p + t2 = t*t + t4 = t2*t2 + t6 = t4*t2 + +! liquid density + a = a0 + a1*p + a2*p2 + b = b0 + b1*p + b2*p2 + c = c0 + c1*p + c2*p2 + d = d0 + d1*p + d2*p2 + e = e0 + e1*p + e2*p2 + f = f0 + f1*p + f2*p2 + g = g0 + g1*p + g2*p2 + + rhow = a + b*t + c*t2 + d*t2*t + e*t4 + f*t4*t + g*t6 + + RETURN + END + + +!#> @brief <description> +!#> @param[in] p <description> +!#> @param[in] t <description> +!#> @param[in] ismpl local sample index +!#> @return rho <description> +!#> @details + DOUBLE PRECISION FUNCTION drhowdt(p,t) + IMPLICIT NONE + DOUBLE PRECISION t, p + DOUBLE PRECISION a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, & + d2, e0, e1, e2, f0, f1, f2, g0, g1, g2 + DATA a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2, e0, e1, & + e2, f0, f1, f2, g0, g1, g2/ + 9.99792877961606D+02, & + + 5.07605113140940D-04, -5.2842547816413D-10, & + + 5.13864847162196D-02, -3.61991396354483D-06, & + + 7.97204102509724D-12, -7.53557031774437D-03, & + + 6.37212093275576D-05, -1.66203631393248D-13, & + + 4.60380647957350D-05, -5.61299059722121D-10, & + + 1.80924436489400D-15, -2.26651454175013D-07, & + + 3.36874416675978D-12, -1.30352149261326D-17, & + + 6.14889851856743D-10, -1.06165223196756D-14, & + + 4.75014903737416D-20, -7.39221950969522D-13, & + + 1.42790422913922D-17, -7.13130230531541D-23/ + +! pure water density temperature derivative + + drhowdt = b0+b1*p+t*(c0+c1*p+c2*p**2)*2d0+b2*p**2+t**2.d0*(d0+d1*p+d2*p**2)*3.d0+ & + t**3*(e0+e1*p+e2*p**2)*4.d0+t**4*(f0+f1*p+f2*p**2)*5.d0+ & + t**5*(g0+g1*p+g2*p**2)*6.d0 + + RETURN + END + +!#> @brief <description> +!#> @param[in] p <description> +!#> @param[in] t <description> +!#> @param[in] ismpl local sample index +!#> @return rho <description> +!#> @details + DOUBLE PRECISION FUNCTION drhowdp(p,t) + IMPLICIT NONE + DOUBLE PRECISION t, p + DOUBLE PRECISION a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, & + d2, e0, e1, e2, f0, f1, f2, g0, g1, g2 + DATA a0, a1, a2, b0, b1, b2, c0, c1, c2, d0, d1, d2, e0, e1, & + e2, f0, f1, f2, g0, g1, g2/ + 9.99792877961606D+02, & + + 5.07605113140940D-04, -5.2842547816413D-10, & + + 5.13864847162196D-02, -3.61991396354483D-06, & + + 7.97204102509724D-12, -7.53557031774437D-03, & + + 6.37212093275576D-05, -1.66203631393248D-13, & + + 4.60380647957350D-05, -5.61299059722121D-10, & + + 1.80924436489400D-15, -2.26651454175013D-07, & + + 3.36874416675978D-12, -1.30352149261326D-17, & + + 6.14889851856743D-10, -1.06165223196756D-14, & + + 4.75014903737416D-20, -7.39221950969522D-13, & + + 1.42790422913922D-17, -7.13130230531541D-23/ + +! pure water density pressure derivative + + drhowdp = b0+b1*p+t*(c0+c1*p+c2*p**2)*2d0+b2*p**2+ & + t**2*(d0+d1*p+d2*p**2)*3d0+t**3*(e0+e1*p+e2*p**2)*4d0+ & + t**4*(f0+f1*p+f2*p**2)*5d0+t**5*(g0+g1*p+g2*p**2)*6d0 + + RETURN + END + diff --git a/props/ice/visf.f90 b/props/ice/visf.f90 new file mode 100644 index 0000000..eb0eef7 --- /dev/null +++ b/props/ice/visf.f90 @@ -0,0 +1,102 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water, +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @param[in] ismpl local sample index +!> @return visf [Pa s] +!> @details +!> rhof(i,j,k,ismpl) calculates the viscosity in (in Pa s) of pure water,\n +!> given temperature (t, in C), and pressure (p,in Pa) at node(i,j,k)\n +!> derived from the formulation given in:\n +!> zylkovskij et al: models and methods summary for\n +!> the fehmn application,\n +!> ecd 22, la-ur-94-3787, los alamos nl, 1994.\n +!> Speedy, R.J. (1987) Thermodynamic properties of supercooled water\n +!> at 1 atm. Journal of Physical Chemistry, 91: 3354–3358. +!> range of validity:\n +!> pressures 0.01 - 110 mpa,\n +!> temperature 15 - 350 °c and -46°c - 0°c\n +!> input:\n +!> pressure plocal [Pa]\n +!> temperature tlocal in [C]\n + DOUBLE PRECISION FUNCTION visf(i,j,k,ismpl) + use arrays + use mod_flow + IMPLICIT NONE + + INTEGER i, j, k, ismpl + DOUBLE PRECISION cf(20), bf(6) + DOUBLE PRECISION ta, tb, tlocal, plocal, t, t2, t3, tred, p, & + p2, p3, p4, tp, t2p, tp2 + + DATA cf/0.17409149D-02, 0.18894882D-04, -0.66439332D-07, & + -0.23122388D-09, -0.31534914D-05, 0.11120716D-07, & + -0.48576020D-10, 0.28006861D-07, 0.23225035D-09, & + 0.47180171D-10, 0.10000000D+01, 0.10523153D-01, & + -0.22658391D-05, -0.31796607D-06, 0.29869141D-01, & + 0.21844248D-03, -0.87658855D-06, 0.41690362D-03, & + -0.25147022D-05, 0.22144660D-05/ +! new: after Speedy (1987) for T < 0 to -46 C + DATA bf/26.312D0, -144.565D0, 1239.075D0, -8352.579D0, & + 31430.760, -48576.798D0/ +! end new + + plocal = pres(i,j,k,ismpl)*pa_conv1 + tlocal = temp(i,j,k,ismpl) + IF (tlocal<-45D0) tlocal = -45.D0 + + IF (tlocal<0.D0) THEN +! tloCal = 0.d0 +! new: after Speedy (1987) for T < 0 to -46 C + tred = (tlocal+273.15D0-227.15D0)/227.15D0 + visf = bf(1)/sqrt(tred) + bf(2) + bf(3)*tred + & + bf(4)*tred*tred + bf(5)*tred*tred*tred + & + bf(6)*tred*tred*tred*tred + visf = visf*0.001 + ELSE +! end new + IF (tlocal>300.D0) tlocal = 300.D0 + + p = plocal + t = tlocal + p2 = p*p + p3 = p2*p + p4 = p3*p + t2 = t*t + t3 = t2*t + tp = p*t + t2p = t2*p + tp2 = t*p2 + + ta = cf(1) + cf(2)*p + cf(3)*p2 + cf(4)*p3 + cf(5)*t + & + cf(6)*t2 + cf(7)*t3 + cf(8)*tp + cf(10)*t2p + cf(9)*tp2 + tb = cf(11) + cf(12)*p + cf(13)*p2 + cf(14)*p3 + cf(15)*t + & + cf(16)*t2 + cf(17)*t3 + cf(18)*tp + cf(20)*t2p + & + cf(19)*tp2 + visf = ta/tb + END IF + + RETURN + END diff --git a/shem_fw.f90 b/shem_fw.f90 new file mode 100644 index 0000000..f820bf1 --- /dev/null +++ b/shem_fw.f90 @@ -0,0 +1,137 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief main program for forward simulation (only) +!> @details +!> +!> **SHEMAT-Suite (Simulator for HEat and MAss Transport)** is a +!> numerical code for computing flow, heat and species transport +!> equations in porous media. The governing equations of the code are +!> the groundwater flow equation, the heat transport equation and the +!> species transport equation. \n\n +!> +!> SHEMAT-Suite includes parameter estimation and data assimilation +!> approaches, both stochastic (Monte Carlo, ensemble Kalman filter) +!> and deterministic (Bayesian inversion using automatic +!> differentiation for calculating derivatives).\n\n +!> +!> Note: To be able to use input file parsing with hdf5, the +!> hdf5-input-files have to be generated using the script: +!> `convert_to_hdf5.py`. This script can be found in the repository +!> `SHEMAT-Suite_Scripts` under +!> `python/preprocessing/convert_to_hdf5.py`. +program shem_fw + use arrays + use mod_genrl + use mod_genrlc + use mod_time +#ifndef noHDF + use mod_input_file_parser_hdf5 +#endif + implicit none + + ! Global sampling index + integer :: ismpl + + ! Starting time of SHEMAT-Suite execution + double precision :: tsglobal + + ! Finishing time of SHEMAT-Suite execution + double precision :: tfglobal + + ! Runtime of SHEMAT-Suite execution + double precision ::ttglobal + + ! Number of full minutes in runtime + integer :: tmins + + ! Include version information from compilation + INCLUDE 'version.inc' + + ! SHEMAT-Suite input filename read from shemade.job + character (len=80) :: filename + + + CALL sys_cputime(tsglobal) + + ismpl = 1 + + write(*,*) ' ' + write(*,*) '======================================' + write(*,*) version + write(*,*) '======================================' + write(*,*) ' ' + + open(unit = 66, file='shemade.job') + + ! ----------------------------------------- + + ! read new input file name +10 read(unit = 66, fmt = '(A)', end = 99999) filename + + if (filename(1:1)=='!') go to 10 + if (filename(1:1)=='%') go to 10 + if (filename(1:1)=='#') go to 10 + + write(unit = *, fmt = *) ' ' + write(unit = *, fmt = *) ' ' + write(unit = *, fmt = *) ' *** NEW MODEL ' + + project = filename + runmode = 0 + transient = .false. + + ! reading input + call forward_preparation(filename, ismpl) + + ! initialize + call forward_init(ismpl) + + ! --------- + call forward_iter(simtime_0,max_simtime,ismpl) + ! --------- + + ! output + call forward_write(-1,ismpl) + if (runmode > 0) call write_data(-1,ismpl) + + call dealloc_arrays(ismpl) + call props_end(ismpl) + call dealloc_data(ismpl) + + ! Another file to load? + go to 10 + + ! ----------------------------------------- + + ! finis terrae +99999 continue + ! + close(unit = 66) + call sys_cputime(tfglobal) + ttglobal = tfglobal - ttglobal + tmins = int(ttglobal/60.D0) + write(unit = *, fmt = '(1A,1I4,1A,1F5.2,1A)') ' total cpu time: ', tmins, ':', & + ttglobal - dble(tmins)*60.D0, ' min' + write(unit = *, fmt = *) 'RUN O.K.' + ! +end program shem_fw diff --git a/solve/CMakeLists.txt b/solve/CMakeLists.txt new file mode 100644 index 0000000..52d6644 --- /dev/null +++ b/solve/CMakeLists.txt @@ -0,0 +1,30 @@ +# MIT License +# +# Copyright (c) 2020 SHEMAT-Suite +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in all +# copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. + +file(GLOB SRC_SOLVE counter.f90 mod_blocking_size.f90 omp_bayes_solve.f90 omp_mvp2.f90 omp_sym_solve_ilu.f90 preconditioners.f90 solve_debug.f90 +ddl_du.f90 mod_OMP_TOOLS.f90 omp_damax.f90 omp_mvp.f90 omp_sym_solve_ssor.f90 prepare_solve.f90 solve.f90 +dense_solve.f90 nag_gen_solve.f90 omp_ddot.f90 OMP_TOOLS.f90 qddot.f90 solve_type.f90 +direct_solve.f90 norm_linsys2.f90 omp_gen_solve_diag.f90 par_tools.f90 reduction.f90 ssor_mvp_single.f90 +get_dnorm.f90 norm_linsys.f90 omp_gen_solve.f90 omp_preconditioners.f90 p_pos_anz.f90 set_dval.f90 test_matrix.f90 +get_norm2.f90 norm_resid.f90 omp_gen_solve_ilu.f90 omp_sym_solve_diag.f90 pre_bicgstab.f90 set_ival.f90 test_symmetry.f90 +get_norm.f90 omp_abbruch.f90 omp_gen_solve_ssor.f90 omp_sym_solve.f90 pre_cg.f90 set_lval.f90 test_zero.f90 ) +add_library(solve ${SRC_SOLVE}) diff --git a/solve/OMP_TOOLS.f90 b/solve/OMP_TOOLS.f90 new file mode 100644 index 0000000..bbcd774 --- /dev/null +++ b/solve/OMP_TOOLS.f90 @@ -0,0 +1,52 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP wrapper for "omp_get_thread_num" +!> @return thread index number + INTEGER FUNCTION omp_get_his_thread_num() + IMPLICIT NONE + INTEGER n +!$ integer (kind=4) :: OMP_GET_THREAD_NUM +!$ external OMP_GET_THREAD_NUM + + n = 0 +!$ N=OMP_GET_THREAD_NUM() + omp_get_his_thread_num = n + + RETURN + END + +!> @brief OpenMP wrapper for "omp_get_num_threads" +!> @return number of threads + INTEGER FUNCTION omp_get_num_of_threads() + IMPLICIT NONE + INTEGER n +!$ integer (kind=4) :: OMP_GET_NUM_THREADS +!$ external OMP_GET_NUM_THREADS + + n = 1 +!$ N=OMP_GET_NUM_THREADS() +!AW-TESTC$ N=OMP_GET_MAX_THREADS() + omp_get_num_of_threads = n + + RETURN + END diff --git a/solve/OMP_TOOLS.inc b/solve/OMP_TOOLS.inc new file mode 100644 index 0000000..45bb90f --- /dev/null +++ b/solve/OMP_TOOLS.inc @@ -0,0 +1,26 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +! local declaration of the two wrapper routines (OpenMP), instead of "omp.h" + integer OMP_GET_his_THREAD_NUM + integer OMP_GET_NUM_of_THREADS + external OMP_GET_his_THREAD_NUM,OMP_GET_NUM_of_THREADS diff --git a/solve/counter.f90 b/solve/counter.f90 new file mode 100644 index 0000000..4329753 --- /dev/null +++ b/solve/counter.f90 @@ -0,0 +1,54 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialisation of the floating point performance counter (only for benchmarking) + SUBROUTINE dp_init() + IMPLICIT NONE + INTEGER dp + COMMON /floating_points/dp + dp = 0 + RETURN + END + +!> @brief increase the floating point performance counter (only for benchmarking) +!> @param[in] n additional number of floating point operations + SUBROUTINE dp_count(n) + IMPLICIT NONE + INTEGER n, dp + COMMON /floating_points/dp +!$OMP atomic + dp = dp + n + RETURN + END + +!> @brief write out the floating point performance (only for benchmarking) +!> @param[in] time run time during benchmark + SUBROUTINE dp_comp(time) + IMPLICIT NONE + DOUBLE PRECISION time + INTEGER dp + COMMON /floating_points/dp + INTRINSIC dble + WRITE(*,'(1A,1F10.2)') ' [I] : MBytes/sec = ', & + dble(dp*8)/(time*1.0D6) + RETURN + END diff --git a/solve/ddl_du.f90 b/solve/ddl_du.f90 new file mode 100644 index 0000000..466dfe4 --- /dev/null +++ b/solve/ddl_du.f90 @@ -0,0 +1,114 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : D*[D+L]^(-1) x [b] = [b^] +!> @param[in] N_I lengths of I-dimension of local matrix [M] +!> @param[in] N_J lengths of J-dimension of local matrix [M] +!> @param[in] N_K lengths of K-dimension of local matrix [M] +!> @param[in] b vector [b] +!> @param[in] MA diagonals of matrix [M] +!> @param[in] MB diagonals of matrix [M] +!> @param[in] MC diagonals of matrix [M] +!> @param[in] MD diagonals of matrix [M] +!> @param[out] b_hat the solution vector [b^] +!> @details +!> solve of : D*[D+L]^(-1) x [b] = [b^]\n +!> with [M]=[L]+[D]+[R]\n + SUBROUTINE ddl(n_i,n_j,n_k,b,b_hat,ma,mb,mc,md) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + INTEGER n_i, n_j, n_k, i, j, k + DOUBLE PRECISION b(n_i,n_j,n_k), b_hat(n_i,n_j,n_k) + DOUBLE PRECISION ma(n_i,n_j,n_k), mb(n_i,n_j,n_k) + DOUBLE PRECISION mc(n_i,n_j,n_k), md(n_i,n_j,n_k) + +! ###################### not parallel Code !!! ######################### +! prepare [b^] +! [b^] = D*(D+L)^(-1) * [b] +!$OMP master + DO k = 1, n_k + DO j = 1, n_j + DO i = 1, n_i + b_hat(i,j,k) = b(i,j,k) + IF (i>1) b_hat(i,j,k) = b_hat(i,j,k) - & + mc(i,j,k)*b_hat(i-1,j,k) + IF (j>1) b_hat(i,j,k) = b_hat(i,j,k) - & + mb(i,j,k)*b_hat(i,j-1,k) + IF (k>1) b_hat(i,j,k) = b_hat(i,j,k) - & + ma(i,j,k)*b_hat(i,j,k-1) +!AW ugly hack ... + IF (md(i,j,k)/=0.0D0) THEN + b_hat(i,j,k) = b_hat(i,j,k)/md(i,j,k) + END IF + END DO + END DO + END DO + DO k = 1, n_k + DO j = 1, n_j + DO i = 1, n_i + b_hat(i,j,k) = b_hat(i,j,k)*md(i,j,k) + END DO + END DO + END DO +!$OMP end master +! ################### above not parallel Code !!! ###################### + RETURN + END + +!> @brief solve of : [D+U]^(-1) x [x^] = [x] +!> @param[in] N_I lengths of I-dimension of local matrix [M] +!> @param[in] N_J lengths of J-dimension of local matrix [M] +!> @param[in] N_K lengths of K-dimension of local matrix [M] +!> @param[in] x_hat vector [x^] +!> @param[in] MD diagonals of matrix [M] +!> @param[in] ME diagonals of matrix [M] +!> @param[in] MF diagonals of matrix [M] +!> @param[in] MG diagonals of matrix [M] +!> @param[out] x the solution vector [x] + SUBROUTINE du(n_i,n_j,n_k,x_hat,x,md,me,mf,mg) + IMPLICIT NONE + INTEGER n_i, n_j, n_k, i, j, k + DOUBLE PRECISION x(n_i,n_j,n_k), x_hat(n_i,n_j,n_k) + DOUBLE PRECISION md(n_i,n_j,n_k), me(n_i,n_j,n_k) + DOUBLE PRECISION mf(n_i,n_j,n_k), mg(n_i,n_j,n_k) + +! ###################### not parallel Code !!! ######################### +! compute [x] +! [x] = (D+U)^(-1) * [x^] + DO k = n_k, 1, -1 + DO j = n_j, 1, -1 + DO i = n_i, 1, -1 + x(i,j,k) = x_hat(i,j,k) + IF (i<n_i) x(i,j,k) = x(i,j,k) - me(i,j,k)*x(i+1,j,k) + IF (j<n_j) x(i,j,k) = x(i,j,k) - mf(i,j,k)*x(i,j+1,k) + IF (k<n_k) x(i,j,k) = x(i,j,k) - mg(i,j,k)*x(i,j,k+1) +!AW ugly hack ... + IF (md(i,j,k)/=0.0D0) THEN + x(i,j,k) = x(i,j,k)/md(i,j,k) + END IF + END DO + END DO + END DO +! ################### above not parallel Code !!! ###################### + RETURN + END diff --git a/solve/dense_solve.f90 b/solve/dense_solve.f90 new file mode 100644 index 0000000..490c871 --- /dev/null +++ b/solve/dense_solve.f90 @@ -0,0 +1,106 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief linear system solver [x]:=[A^-1]x[b], dense matrix (quadratic) +!> @param[in] NIJK system size +!> @param[in] NRHS number of right sides/solutions +!> @param[in] A system matrix +!> @param[in] B rigth side +!> @param[out] X solution +!#> @details + SUBROUTINE dense_solve(nijk,nrhs,a,b,x) + use mod_linfos + IMPLICIT NONE + INTEGER nijk, nrhs, isnull + INTEGER, ALLOCATABLE :: pivots(:) + DOUBLE PRECISION, ALLOCATABLE :: tmp(:), tmpm(:,:) + INTEGER error + DOUBLE PRECISION a(nijk,nijk), b(nijk,nrhs) + DOUBLE PRECISION x(nijk,nrhs), enough, enough2 + + + IF ((8.0D0*dble(2*nijk+nijk*nijk))>2.0D9) THEN + WRITE(*,'(A,A,F9.4,A)') & + 'Error: array to large for direct dense', & + ' matrix solver (', 8.0D0*dble(2*nijk+nijk*nijk)/1024.0D0 & + **3, ' GBytes).' + STOP + END IF + + ALLOCATE(pivots(nijk)) + ALLOCATE(tmp(nijk)) + ALLOCATE(tmpm(nijk,nijk)) + error = 0 + CALL set_ival(nijk,0,pivots) + +! right side to [X] + CALL dcopy(nijk*nrhs,b,1,x,1) +! copy matrix + CALL dcopy(nijk*nijk,a,1,tmpm,1) + +! -------------------------------------------------------------- + +! solve dense matrix + CALL dgesv(nijk,nrhs,a,nijk,pivots,x,nijk,error) + + IF (error>0) THEN + WRITE(*,*) ' dense PLU: ', error, 'errors were found.' + ELSE IF (linfos(4)>=1) THEN +!aw write(*,*) ' dense PLU finished.' + END IF + + IF ((linfos(4)>=1) .AND. (nrhs==1)) THEN +! MVP +! [tmp]==[r]:=[A]x[x] + CALL dgemv('N',nijk,nijk,1.0D0,tmpm,nijk,x,1,0.0D0,tmp,1) + + enough = 0.0D0 + isnull = 0 + enough2 = 0.0D0 + CALL s_ddot(nijk,b,b,enough) + CALL test_zero(enough,1,isnull) + IF (isnull/=1) THEN + CALL s_ddot(nijk,tmp,tmp,enough2) + enough2 = abs(enough-enough2)/(enough) + END IF + +! [r]:=[w]-[A]x[x] + CALL dscal(nijk,-1.0D0,tmp,1) + CALL daxpy(nijk,1.0D0,b,1,tmp,1) + + enough = 0.0D0 + CALL s_ddot(nijk,tmp,tmp,enough) + WRITE(*,'(2(a,e12.5))') ' PLU: nrm2(R)', dsqrt(enough), & + ' rel=', enough2 + END IF + +! restore matrix (only needed for debug) + CALL dcopy(nijk*nijk,tmpm,1,a,1) + + DEALLOCATE(pivots) + DEALLOCATE(tmp) + DEALLOCATE(tmpm) + +! -------------------------------------------------------------- + + RETURN + END diff --git a/solve/direct_solve.f90 b/solve/direct_solve.f90 new file mode 100644 index 0000000..6c46cf9 --- /dev/null +++ b/solve/direct_solve.f90 @@ -0,0 +1,165 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief direct linear solver call: PLU from LAPACK, solve of : [M] x [x] = [b] +!> @param[in] I0 lengths of I-dimension of local matrix [M] +!> @param[in] J0 lengths of J-dimension of local matrix [M] +!> @param[in] K0 lengths of K-dimension of local matrix [M] +!> @param[out] x solution vector [x] +!> @param[in] w right side, vector [b] +!> @param[in] A 1. diagonal of the system matrix [M] +!> @param[in] B 2. diagonal of the system matrix [M] +!> @param[in] C 3. diagonal of the system matrix [M] +!> @param[in] D 4. diagonal of the system matrix [M] +!> @param[in] E 5. diagonal of the system matrix [M] +!> @param[in] F 6. diagonal of the system matrix [M] +!> @param[in] G 7. diagonal of the system matrix [M] + SUBROUTINE direct_solve(i0,j0,k0,x,w,a,b,c,d,e,f,g) + use mod_linfos + IMPLICIT NONE + + INTEGER i0, j0, k0, kl, ku, ldm + + DOUBLE PRECISION, ALLOCATABLE :: matrix(:,:) + INTEGER, ALLOCATABLE :: pivots(:) + INTEGER error, i, j, k, ind, nijk + +! need to detect 64Bit enviroment + INTEGER test32 + INTEGER (kind=8) test64 + + DOUBLE PRECISION x(i0,j0,k0), w(i0,j0,k0), enough, enough2 + DOUBLE PRECISION a(i0,j0,k0), b(i0,j0,k0), c(i0,j0,k0), & + d(i0,j0,k0), e(i0,j0,k0), f(i0,j0,k0), g(i0,j0,k0) + + + nijk = i0*j0*k0 + kl = i0*j0 + IF (i0==1) kl = i0*j0 + IF (j0==1) kl = i0*j0 + IF (k0==1) kl = i0 + ku = kl + ldm = 2*kl + ku + 1 + +! detecting 64Bit-Integer enviroment (t32=t64 for 64Bit) + test32 = 3000000 + test64 = 3000000 + test32 = test32*test32 + test64 = test64*test64 + +! protecting against 32 pointers + IF ((8.0D0*dble(ldm)*dble(nijk))>2.0D9) THEN + IF (test32==test64) THEN + WRITE(*,'(A,A)') 'Warning: try to use 64Bit integer', & + ' enviroment (needs 64Bit system)' + ELSE + WRITE(*,'(A,A,F9.4,A)') & + 'Error: array to large for direct band', & + ' matrix solver (', 8.0D0*dble(ldm)*dble(nijk)/1024.0D0 & + **3, ' GBytes).' + STOP + END IF + END IF + + ALLOCATE(matrix(ldm,nijk)) + ALLOCATE(pivots(nijk)) + error = 0 + +! right side to [X] + CALL dcopy(nijk,w,1,x,1) + CALL set_dval(ldm*nijk,0.D0,matrix) + +! -------------------------------------------------------------- + + ind = 0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 +!aw ind=i +I0*(j-1) +I0*J0*(k-1) + ind = ind + 1 +! if (i<20 .and. j==1 .and. k==1) write(*,*) "d(",i,",",j,",",k,")=",d(i,j,k) + IF (d(i,j,k)==0.0D0) THEN + WRITE(*,'(A,3I5,A,2e15.8)') & + 'error in direct_solve.f90: main diagonal element equal to zero at ', i, & + j, k, '=', d(i,j,k) + STOP + ELSE +! copy diagonals into band strukture + matrix(ldm-kl,ind) = d(i,j,k) + IF (ind>1 .AND. i0>1) matrix(ldm-kl+1,ind-1) = c(i,j, & + k) + IF (ind<=nijk-1 .AND. i0>1) matrix(ldm-kl-1,ind+1) & + = e(i,j,k) + + IF (ind>i0 .AND. j0>1) matrix(ldm-kl+i0,ind-i0) = b(i, & + j,k) + IF (ind<=nijk-i0 .AND. j0>1) matrix(ldm-kl-i0,ind+i0) & + = f(i,j,k) + + IF (ind>i0*j0 .AND. k0>1) matrix(ldm-kl+i0*j0, & + ind-i0*j0) = a(i,j,k) + IF (ind<=nijk-i0*j0 .AND. k0>1) matrix(ldm-kl-i0*j0, & + ind+i0*j0) = g(i,j,k) + END IF + + END DO + END DO + END DO + +!aw call dgesv(NIJK,1,matrix,NIJK,pivots,X,NIJK,error) + CALL dgbsv(nijk,kl,ku,1,matrix,ldm,pivots,x,nijk,error) + +! -------------------------------------------------------------- + + IF ((linfos(4)>=2) .OR. (error>0)) THEN + WRITE(*,*) ' PLU: ', error, 'errors was found.' + END IF + +! print latest, "matrix" is used as tmp. vector + IF (linfos(4)>=1) THEN +! MVP +! [r=matrix]:=[A]x[x] + CALL s_mvp(i0,j0,k0,x,matrix,a,b,c,d,e,f,g) +! [r]:=[w]-[A]x[x] + CALL dscal(nijk,-1.0D0,matrix,1) + CALL daxpy(nijk,1.0D0,w,1,matrix,1) + +! Ueberpruefung, ob Abbruch + enough = 0.0D0 + enough2 = 0.0D0 + + CALL s_damax(nijk,matrix,enough) + CALL s_ddot(nijk,matrix,matrix,enough2) + IF (linfos(4)>=2) THEN + WRITE(*,'(2(1a,1d20.13))') ' damax(R) =', enough, & + ', nrm2(R)', dsqrt(enough2) + ELSE + WRITE(*,'(1a,1d20.13,1a)') ' nrm2(R) =', dsqrt(enough2), & + ' (direct)' + END IF + END IF + + DEALLOCATE(matrix) + DEALLOCATE(pivots) + + RETURN + END diff --git a/solve/get_dnorm.f90 b/solve/get_dnorm.f90 new file mode 100644 index 0000000..8b4cc36 --- /dev/null +++ b/solve/get_dnorm.f90 @@ -0,0 +1,57 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief return modified diagonal prepared for normalisation +!> @param[in] md diagonal (system matrix) +!> @param[in] mbc_mask boundary mask +!> @param[in] N number of elements, vector length +!> @param[out] dnrm normalisation vector + SUBROUTINE get_dnorm(n,mbc_mask,md,dnrm) + IMPLICIT NONE + INTEGER n, i + DOUBLE PRECISION dnrm(n), dcrit_nrm +! diagonal (system matrix) + DOUBLE PRECISION md(n) +! boundary mask + CHARACTER mbc_mask(n) + INTRINSIC dsqrt, dabs, dble + LOGICAL test_null + EXTERNAL test_null + +! correction for 2-Norm + dcrit_nrm = dsqrt(dble(n)) + + DO i = 1, n + dnrm(i) = 0.D0 +! add, since it is no boundary condition element + IF (mbc_mask(i)=='+') THEN + IF (test_null(md(i))) THEN + WRITE(*,*) 'zero at ', i, md(i), mbc_mask(i) + END IF +! important: diagonal dominance +! used for adaptive scaling the residuum + dnrm(i) = 1.D0/dabs(md(i)*dcrit_nrm) + END IF + END DO +! + RETURN + END diff --git a/solve/get_norm.f90 b/solve/get_norm.f90 new file mode 100644 index 0000000..e309552 --- /dev/null +++ b/solve/get_norm.f90 @@ -0,0 +1,59 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief return normalisation-vector for initial normalisation of the linear-system +!> @param[in] mw right side, solution, diagonal (system matrix) +!> @param[in] mbc_mask boundary mask +!> @param[in] N number of elements, vector length +!> @param[in] md diagonal of the system matrx +!> @param[in] mx currentr solution vector (used for step by step updates) +!> @param[out] dnormalise updated (new) normalisation vector + SUBROUTINE get_norm(n,mw,mbc_mask,md,mx,dnormalise) + IMPLICIT NONE + INTEGER n, i + DOUBLE PRECISION dnormalise(n), dcrit_nrm +! right side, solution, diagonal (system matrix) + DOUBLE PRECISION mw(n), mx(n), md(n) +! boundary mask + CHARACTER mbc_mask(n) + INTRINSIC dsqrt, dabs, dble + LOGICAL test_null + EXTERNAL test_null + +! correction for 2-Norm + dcrit_nrm = dsqrt(dble(n)) + + DO i = 1, n + dnormalise(i) = 1.D0 +! add, since it is no boundary condition element + IF (mbc_mask(i)=='+') THEN +! important: diagonal dominance + IF ( .NOT. test_null(mx(i))) THEN + dnormalise(i) = 1.D0/dabs(md(i)*mx(i)*dcrit_nrm) + ELSE + dnormalise(i) = 1.D0/(max(dabs(md(i)),dabs(mw(i)))*dcrit_nrm) + END IF + END IF + END DO +! + RETURN + END diff --git a/solve/get_norm2.f90 b/solve/get_norm2.f90 new file mode 100644 index 0000000..e246d4e --- /dev/null +++ b/solve/get_norm2.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief return normalisation-vector for initial normalisation of the linear-system +!> @param[in] mw right side, solution, diagonal (system matrix) +!> @param[in] mbc_mask boundary mask +!> @param[in] N number of elements, vector length +!> @param[in] md diagonal of the system matrx +!> @param[in] mx currentr solution vector (used for step by step updates) +!> @param[out] dnormalise updated (new) normalisation vector +!> @param[in] soddmx second offset (dominant) diagonal*mx + SUBROUTINE get_norm2(n,mw,mbc_mask,md,mx,dnormalise,soddmx) + IMPLICIT NONE + INTEGER n, i + DOUBLE PRECISION dnormalise(n), dcrit_nrm +! right side, solution, diagonal (system matrix) + DOUBLE PRECISION mw(n), mx(n), md(n), soddmx(n) +! boundary mask + CHARACTER mbc_mask(n) + INTRINSIC dsqrt, dabs, dble + LOGICAL test_null + EXTERNAL test_null + +! correction for 2-Norm + dcrit_nrm = dsqrt(dble(n)) + + DO i = 1, n + dnormalise(i) = 1.D0 +! add, since it is no boundary condition element + IF (mbc_mask(i)=='+') THEN +! important: diagonal dominance + IF ( .NOT. test_null(mx(i))) THEN + dnormalise(i) = 1.D0 /(max(dabs(md(i)*mx(i)), soddmx(i))*dcrit_nrm) + ELSE + dnormalise(i) = 1.D0 /(max(dabs(md(i)), dabs(mw(i)), soddmx(i))*dcrit_nrm) + END IF + END IF + END DO +! + RETURN + END diff --git a/solve/mod_OMP_TOOLS.f90 b/solve/mod_OMP_TOOLS.f90 new file mode 100644 index 0000000..3479e14 --- /dev/null +++ b/solve/mod_OMP_TOOLS.f90 @@ -0,0 +1,27 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief thread level information +module mod_OMP_TOOLS +! number of threads for level 0(outer region) and 1(inner region) + integer Tlevel_0, Tlevel_1 +end module mod_OMP_TOOLS diff --git a/solve/mod_blocking_size.f90 b/solve/mod_blocking_size.f90 new file mode 100644 index 0000000..207e513 --- /dev/null +++ b/solve/mod_blocking_size.f90 @@ -0,0 +1,43 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solver constants and prozessor cache & block size information +module mod_blocking_size +! processor-cache size, cache-block size + integer cache_size, bl_size +! + integer block_i, block_j, block_k + integer bdim_i, bdim_j, bdim_k + integer max_blocks +! +! chunk size optimisation (for different cases) + double precision bldiv_cg + double precision bldiv_bicg(2) + double precision bldiv_mvp + double precision bldiv_dot(3) +! +! maximal number of temporary vectors needed in a linear system solver +! 1..9: "pre_CG" system solver +! 1..13: "pre_BiCGStab" system solver + integer max_locTMP + parameter (max_locTMP = 13) +end module mod_blocking_size diff --git a/solve/norm_linsys.f90 b/solve/norm_linsys.f90 new file mode 100644 index 0000000..2be9e30 --- /dev/null +++ b/solve/norm_linsys.f90 @@ -0,0 +1,83 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief normalise the linear system, matrix and the right side +!> @param[in] N size of all given vectors +!> @param[in] mbc_mask boundary mask +!> @param[in,out] mw right side, solution +!> @param[in] mx [x]-vector +!> @param[in,out] MA 1. diagonal of the system matrix +!> @param[in,out] MB 2. diagonal of the system matrix +!> @param[in,out] MC 3. diagonal of the system matrix +!> @param[in,out] MD 4. diagonal of the system matrix +!> @param[in,out] ME 5. diagonal of the system matrix +!> @param[in,out] MF 6. diagonal of the system matrix +!> @param[in,out] MG 7. diagonal of the system matrix +!> @param[out] dnormalise normalising vector for adaptive resiuum + SUBROUTINE norm_linsys(n,mbc_mask,mw,mx,ma,mb,mc,md,me,mf,mg,dnormalise) + IMPLICIT NONE + INTEGER n, i +! normalising value + DOUBLE PRECISION dnormalise(n) +! matrix coefficients + DOUBLE PRECISION ma(n), mb(n), mc(n), md(n), me(n), mf(n), & + mg(n) +! right side, solution + DOUBLE PRECISION mw(n), mx(n) + CHARACTER mbc_mask(n) + + +! get the norm.-vector for initial normalisation of the system + CALL get_norm(n,mw,mbc_mask,md,mx,dnormalise) + +! normalise the system matrix + DO i = 1, n + ma(i) = ma(i)*dnormalise(i) + END DO + DO i = 1, n + mb(i) = mb(i)*dnormalise(i) + END DO + DO i = 1, n + mc(i) = mc(i)*dnormalise(i) + END DO + DO i = 1, n + md(i) = md(i)*dnormalise(i) + END DO + DO i = 1, n + me(i) = me(i)*dnormalise(i) + END DO + DO i = 1, n + mf(i) = mf(i)*dnormalise(i) + END DO + DO i = 1, n + mg(i) = mg(i)*dnormalise(i) + END DO +! normalise the right side + DO i = 1, n + mw(i) = mw(i)*dnormalise(i) + END DO + +! get the prepared/updated normalisation vector + CALL get_dnorm(n,mbc_mask,md,dnormalise) + + RETURN + END diff --git a/solve/norm_linsys2.f90 b/solve/norm_linsys2.f90 new file mode 100644 index 0000000..e173262 --- /dev/null +++ b/solve/norm_linsys2.f90 @@ -0,0 +1,84 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief normalise the linear system, matrix and the right side +!> @param[in] N size of all given vectors +!> @param[in] mbc_mask boundary mask +!> @param[in,out] mw right side, solution +!> @param[in] mx [x]-vector +!> @param[in,out] MA 1. diagonal of the system matrix +!> @param[in,out] MB 2. diagonal of the system matrix +!> @param[in,out] MC 3. diagonal of the system matrix +!> @param[in,out] MD 4. diagonal of the system matrix +!> @param[in,out] ME 5. diagonal of the system matrix +!> @param[in,out] MF 6. diagonal of the system matrix +!> @param[in,out] MG 7. diagonal of the system matrix +!> @param[in,out] dnormalise normalising vector for adaptive resiuum (disabled function - working on matnormalise), as input initialised with second offset (dominant) diagonal*x +!> @param[out] matnormalise normalising vector for matrix system + SUBROUTINE norm_linsys2(n,mbc_mask,mw,mx,ma,mb,mc,md,me,mf,mg,dnormalise,matnormalise) + IMPLICIT NONE + INTEGER n, i +! normalising value + DOUBLE PRECISION dnormalise(n), matnormalise(n) +! matrix coefficients + DOUBLE PRECISION ma(n), mb(n), mc(n), md(n), me(n), mf(n), & + mg(n) +! right side, solution + DOUBLE PRECISION mw(n), mx(n) + CHARACTER mbc_mask(n) + + +! get the norm.-vector for the normalisation of the system (in "matnormalise") + CALL get_norm2(n,mw,mbc_mask,md,mx,matnormalise,dnormalise) + +! normalise the system matrix + DO i = 1, n + ma(i) = ma(i)*matnormalise(i) + END DO + DO i = 1, n + mb(i) = mb(i)*matnormalise(i) + END DO + DO i = 1, n + mc(i) = mc(i)*matnormalise(i) + END DO + DO i = 1, n + md(i) = md(i)*matnormalise(i) + END DO + DO i = 1, n + me(i) = me(i)*matnormalise(i) + END DO + DO i = 1, n + mf(i) = mf(i)*matnormalise(i) + END DO + DO i = 1, n + mg(i) = mg(i)*matnormalise(i) + END DO +! normalise the right side + DO i = 1, n + mw(i) = mw(i)*matnormalise(i) + END DO + +! disable the adaptive normalisation (normalisation vector = 0) + CALL set_dval(n,0.0d0,dnormalise) + + RETURN + END diff --git a/solve/norm_resid.f90 b/solve/norm_resid.f90 new file mode 100644 index 0000000..1476575 --- /dev/null +++ b/solve/norm_resid.f90 @@ -0,0 +1,46 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief adaptive update normalisation of the residuum +!> @param[in] N vector length +!> @param[in] dnrm main part of the normalisation vector +!> @param[in] xval current result vector, needed for normalisation +!> @param[out] rval update vector + SUBROUTINE norm_resid(n,dnrm,xval,rval) + IMPLICIT NONE + INTEGER n, i + DOUBLE PRECISION dtmp, dnrm(n), xval(n), rval(n) + LOGICAL test_null + EXTERNAL test_null + INTRINSIC dabs + + DO i = 1, n + IF ( .NOT. test_null(dnrm(i))) THEN + IF ( .NOT. test_null(xval(i))) THEN + dtmp = dnrm(i)/dabs(xval(i)) + rval(i) = rval(i)*dtmp + END IF + END IF + END DO +! + RETURN + END diff --git a/solve/omp_abbruch.f90 b/solve/omp_abbruch.f90 new file mode 100644 index 0000000..b9fad73 --- /dev/null +++ b/solve/omp_abbruch.f90 @@ -0,0 +1,277 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief probe for break criteria, (OpenMP version) +!> @param[in] enough value for ||[res]|| or max(abs(res)), see 'criteria' +!> @param[in] iter count iterations +!> @param[in] max_It maximum of iterations, counted with 'iter' +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] need_Ax switch to compute an extra MVP:([A]x[x]) in [ax], see 'criteria' +!> @param[in] criteria switch to set when should break\n +!> - 0 : relative stopping crit. : ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit. : ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit. : max(abs([res])) < depsilon\n +!> - 3 : abs. and rel. stopping crit. : ( ||[res]|| < depsilon ) and ( ||[res]|| < 0.5d0*||[res0]|| )\n +!> 0.5d0 is a constant for testing only and is named 'minRel'\n +!> first [res] ^= [r_0] and later (if precise enough) : [res] ^= ([A]x[x]-[b]) +!> @param[in] res0 res0 ^= ||[res0]||, should be start residue +!> @param[in] divide_zero (>0) division by zero ? +!> @param[in,out] e_count counts the number of reaching the criteria +!> @param[in,out] e_old last good `enough` value +!> @return false : continue (not enough precision), true : break - enough precision or max_It reached + LOGICAL FUNCTION omp_abbruch(enough,iter,max_it,depsilon, & + need_ax,criteria,res0,divide_zero,e_count,e_old) + use mod_OMP_TOOLS + use mod_linfos + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! break with enough precision + DOUBLE PRECISION depsilon, enough + DOUBLE PRECISION res0, e_old + INTEGER e_count +! see above + DOUBLE PRECISION minrel + PARAMETER (minrel=0.99D0) +! need_Ax : switch to compute an extra MVP:([A]x[x]) in [ax] +! criteria : switch to break + LOGICAL need_ax, flag_abbruch + INTEGER criteria + character (len=3) :: rstr +! iter : count iterations, +! max_It : max iterations, +! divide_zero <> 0 : break should be done too + INTEGER iter, max_it, divide_zero + INTRINSIC dsqrt + + + rstr = '[r]' + IF (need_ax) rstr = '(R)' + +! default -> break iterations + flag_abbruch = .TRUE. + +! max-iterations reached ? + IF (iter>max_it) GO TO 100 + +! same result the last three times ? + IF ((e_count>3) .AND. (e_old==enough)) THEN +!$OMP master + IF (linfos(4)>=1) WRITE(*,*) & + ' Warning : stopping before precision reached' +!$OMP end master + GO TO 100 + END IF + +! enough precision ? + + IF (criteria==1) THEN +! absolute +! write(*,*) "Testing absolute ",enough,"<=",depsilon*depsilon,"?" + IF (enough<=(depsilon*depsilon)) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==2) THEN +! maximum +! write(*,*) "Testing maximum ",enough,"<=",depsilon,"?" + IF (enough<=depsilon) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==3) THEN +! absolute and relative +! write(*,*) "Testing absolut and relative ",enough,"<=",res0*res0*minrel*minrel," and",depsilon*depsilon,"?" + IF ((enough<=(res0*res0*minrel*minrel)) .AND. (enough<=( & + depsilon*depsilon))) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==0) THEN +! relative +! write(*,*) "Testing relative ",enough,"<=",depsilon*res0*depsilon*res0 + IF (enough<=(depsilon*res0*depsilon*res0)) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + END IF + +! continue, no break + IF (divide_zero==0) flag_abbruch = .FALSE. + + IF (e_old==enough) THEN + e_count = e_count + 1 + ELSE + e_old = enough + e_count = 0 + END IF + +! stop label +100 CONTINUE + +333 FORMAT (3A,1D20.13,1A) +!$OMP master +! print latest + IF ((linfos(4)>=1) .AND. (flag_abbruch)) THEN + IF (criteria==2) THEN + WRITE(*,333,advance='NO') ' damax', rstr, ' =', enough, & + ' ' + ELSE + WRITE(*,333,advance='NO') ' nrm2', rstr, ' =', & + dsqrt(enough), ' ' + END IF + ELSE IF (linfos(4)>=3 .AND. linfos(4)/=100) THEN + IF (criteria==2) THEN + WRITE(*,333,advance='NO') ' damax', rstr, ' =', enough, & + ',' + ELSE + WRITE(*,333,advance='NO') ' nrm2', rstr, ' =', & + dsqrt(enough), ',' + END IF + END IF +!$OMP end master + + omp_abbruch = flag_abbruch + RETURN + END + +!> @brief probe for break criteria, serial (no OpenMP) implementation of "omp_abbruch", see above +!> @param[in] enough value for ||[res]|| or max(abs(res)), see 'criteria' +!> @param[in] iter count iterations +!> @param[in] max_It maximum of iterations, counted with 'iter' +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] need_Ax switch to compute an extra MVP:([A]x[x]) in [ax], see 'criteria' +!> @param[in] criteria switch to set when should break\n +!> - 0 : relative stopping crit. : ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit. : ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit. : max(abs([res])) < depsilon\n +!> - 3 : abs. and rel. stopping crit. : ( ||[res]|| < depsilon ) and ( ||[res]|| < 0.5d0*||[res0]|| )\n +!> 0.5d0 is a constant for testing only and is named 'minRel'\n +!> first [res] ^= [r_0] and later (if precise enough) : [res] ^= ([A]x[x]-[b]) +!> @param[in] res0 res0 ^= ||[res0]||, should be start residue +!> @param[in] divide_zero (>0) division by zero ? +!> @param[in,out] e_count counts the number of reaching the criteria +!> @param[in,out] e_old last good `enough` value +!> @return false : continue (not enough precision), true : break - enough precision or max_It reached + LOGICAL FUNCTION s_abbruch(enough,iter,max_it,depsilon,need_ax, & + criteria,res0,divide_zero,e_count,e_old) + use mod_linfos + IMPLICIT NONE +! break with enough precision + DOUBLE PRECISION depsilon, enough + DOUBLE PRECISION res0, e_old + INTEGER e_count +! see above + DOUBLE PRECISION minrel + PARAMETER (minrel=0.99D0) +! need_Ax : switch to compute an extra MVP:([A]x[x]) in [ax] +! criteria : switch to break + LOGICAL need_ax, flag_abbruch + INTEGER criteria + character (len=3) :: rstr +! iter : count iterations, +! max_It : max iterations, +! divide_zero <> 0 : break should be done too + INTEGER iter, max_it, divide_zero + INTRINSIC dsqrt + + + rstr = '[r]' + IF (need_ax) rstr = '(R)' + +! default -> break iterations + flag_abbruch = .TRUE. + +! max-iterations reached ? + IF (iter>max_it) GO TO 100 + +! same result the last three times ? + IF ((e_count>3) .AND. (e_old==enough)) THEN + IF (linfos(4)>=1) WRITE(*,*) & + ' Warning : stopping before precision reached' + GO TO 100 + END IF + +! enough precision ? + + IF (criteria==1) THEN +! absolute + IF (enough<=(depsilon*depsilon)) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==2) THEN +! maximum + IF (enough<=depsilon) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==3) THEN +! absolute and relative + IF ((enough<=(res0*res0*minrel*minrel)) .AND. (enough<=( & + depsilon*depsilon))) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + ELSE IF (criteria==0) THEN +! relative + IF (enough<=(depsilon*res0*depsilon*res0)) THEN + IF (need_ax) GO TO 100 + need_ax = .TRUE. + END IF + END IF + +! continue, no break + IF (divide_zero==0) flag_abbruch = .FALSE. + + IF (e_old==enough) THEN + e_count = e_count + 1 + ELSE + e_old = enough + e_count = 0 + END IF + +! stop label +100 CONTINUE + +333 FORMAT (3A,1D20.13,1A) +! print latest + IF ((linfos(4)>=1) .AND. (flag_abbruch)) THEN + IF (criteria==2) THEN + WRITE(*,333,advance='NO') ' damax', rstr, ' =', enough, & + ' ' + ELSE + WRITE(*,333,advance='NO') ' nrm2', rstr, ' =', & + dsqrt(enough), ' ' + END IF + ELSE IF (linfos(4)>=3 .AND. linfos(4)/=100) THEN + IF (criteria==2) THEN + WRITE(*,333,advance='NO') ' damax', rstr, ' =', enough, & + ',' + ELSE + WRITE(*,333,advance='NO') ' nrm2', rstr, ' =', & + dsqrt(enough), ',' + END IF + END IF + + s_abbruch = flag_abbruch + RETURN + END diff --git a/solve/omp_bayes_solve.f90 b/solve/omp_bayes_solve.f90 new file mode 100644 index 0000000..b2ce255 --- /dev/null +++ b/solve/omp_bayes_solve.f90 @@ -0,0 +1,190 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [Bayes] x [x] = [b], BICGSTAB algorithm based +!> @param[in] N dimension of the matrix [Bayes] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[out] locTMP local temporary vectors +!> @param[out] DATTMP additional data temporary vectors +!> @param[in,out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [Bayes] x [x] = [b]\n +!> [Bayes] is a indirect defined Matrix\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_bayes_solve(N,x,b,r0_hat,depsilon,max_it,criteria,loctmp,dattmp,dnrm,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + use mod_linfos + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER N, max_it, ismpl +! thread stuff + INTEGER tpos, tanz +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(N), b(N) + DOUBLE PRECISION r0_hat(N), res0 +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(N,max_loctmp) + DOUBLE PRECISION dattmp(*), dnrm(N) +! Pre_BiCGStab stuff +! work : control variable : what is to do in this subroutine, +! see more discription in 'pre_bicgstab.inc', +! on startup should set to 'work=START' + INTEGER work +! break with enough precision + DOUBLE PRECISION depsilon +! + INTEGER criteria, linfos_old + INTEGER l, wieviele + DOUBLE PRECISION dmaxi, dmini, durchs +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + +! +! full number of elements + res0 = 1.D+99 + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_0)& +!$OMP default(shared)& +!$OMP private(tanz,tpos,iii,linfos_old) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 5 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +!$OMP end master + linfos_old = linfos(4) +!$OMP barrier + +! preload ([M]x[x]) in [z] +!$OMP master + CALL step_bayes_tmpm(x,dattmp,loctmp(1,z),ismpl) +!$OMP end master +!$OMP barrier + +! Reverse communication loop for bicgstab +10 CONTINUE + + +! BiCGStab routine + linfos(4) = 1 + CALL pre_bicgstab(tanz,x(tpos),b(tpos),r0_hat(tpos),n, & + loctmp(tpos,1),depsilon,dnrm(tpos),max_it,criteria,res0, & + work,ipar,rpar,lpar) +! implicite barrier here + linfos(4) = linfos_old +!$OMP barrier + +! preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[M]x[y] + IF ((work==do_y_p_v) .OR. (work==more_y_p_v)) THEN +! left precond. + CALL myprco(n,loctmp(1,p),loctmp(1,t_pc)) +! right precond. + CALL myprco(n,loctmp(1,t_pc),loctmp(1,y)) +!$OMP barrier + +!$OMP master + CALL step_bayes_tmpm(loctmp(1,y),dattmp,loctmp(1,v),ismpl) +!$OMP end master +!$OMP barrier + END IF + +! [z]:=[M]x[x], for advanced precision + IF (work==more_y_p_v) THEN +!$OMP master + CALL step_bayes_tmpm(x,dattmp,loctmp(1,z),ismpl) +!$OMP end master +!$OMP barrier + END IF + +! preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[M]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + IF (work==do_z_s_t) THEN +! left precond. + CALL myprco(n,loctmp(1,s),loctmp(1,s_pc)) +! right precond. + CALL myprco(n,loctmp(1,s_pc),loctmp(1,z)) +!$OMP barrier + +!$OMP master + CALL step_bayes_tmpm(loctmp(1,z),dattmp,loctmp(1,t),ismpl) +!$OMP end master +!$OMP barrier + +! left precond. + CALL myprco(n,loctmp(1,t),loctmp(1,t_pc)) +!$OMP barrier + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!$OMP end parallel + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_damax.f90 b/solve/omp_damax.f90 new file mode 100644 index 0000000..8a1c701 --- /dev/null +++ b/solve/omp_damax.f90 @@ -0,0 +1,83 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief computes the maximum of vector [x] and broadcast to all, (OpenMP version) +!> @param[in] N length of vector [x] +!> @param[in] X vector [x] +!> @param[in] sh_max openmp-shared help variable +!> @param[out] MAX_X maximum of [x] + SUBROUTINE omp_damax(n,x,max_x,sh_max) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of vector [x] +! ind : index of maximal element + INTEGER n, i, ind +! vector [x] + DOUBLE PRECISION x(n), sh_max, max_x + INTEGER idamax + EXTERNAL idamax + INTRINSIC dabs + +! orphaning feature needed +!$OMP master +! clear before compute + sh_max = 0.0D0 +!$OMP end master +!$OMP barrier +! +! very simple (slow) variation +!$OMP do schedule(static) reduction(max:sh_max) + DO i = 1, omp_get_num_of_threads() +! compute local maximum + ind = idamax(n,x,1) + IF (ind>=1 .AND. n>=1) sh_max = max(sh_max,dabs(x(ind))) + END DO +!$OMP end do +! barrier here ... +! + max_x = sh_max + RETURN + END + +!> @brief computes the maximum of vector [x], serial (no OpenMP) implementation, see above +!> @param[in] N length of vector [x] +!> @param[in] X vector [x] +!> @param[out] MAX_X maximum of [x] + SUBROUTINE s_damax(n,x,max_x) + IMPLICIT NONE +! N : length of vector [x] +! ind : index of maximal element + INTEGER n, ind +! vector [x] + DOUBLE PRECISION x(n), max_x + INTEGER idamax + EXTERNAL idamax + INTRINSIC dabs + +! very simple (slow) variation +! compute local maximum + max_x = 0.0D0 + ind = idamax(n,x,1) + IF (ind>=1 .AND. n>=1) max_x = dabs(x(ind)) + RETURN + END diff --git a/solve/omp_ddot.f90 b/solve/omp_ddot.f90 new file mode 100644 index 0000000..3f6ce23 --- /dev/null +++ b/solve/omp_ddot.f90 @@ -0,0 +1,259 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute ([x]^T*[y]) distributed and build a global sum, (OpenMP version) +!> @param[in] N length of all vectors +!> @param[in] X vector [x] +!> @param[in] Y vector [y] +!> @param[in] sh_help openmp-shared vector [# threads *1] +!> @param[out] S solution ( [x]^T*[y] ) + SUBROUTINE omp_ddot(n,x,y,s,sh_help) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vector x,y + INTEGER n +! lsum : local-summary +! lsum : source summary +! vectors [x], [y] + DOUBLE PRECISION lsum(1), slsum(1), x(n), y(n), s, sh_help(*) + DOUBLE PRECISION qddot + EXTERNAL qddot + DOUBLE PRECISION ddot + EXTERNAL ddot + +! compute local-sum +#ifdef USE_QDDOT + lsum(1) = qddot(n,x,1,y,1) +#else + lsum(1) = ddot(n,x,1,y,1) +#endif +! compute global sum (OpenMP) + CALL xsum_0(1,lsum,slsum,sh_help) + s = slsum(1) + RETURN + END + +!> @brief compute ([x]^T*[y]) and build the sum, serial (no OpenMP) implementation +!> @param[in] N length of all vectors +!> @param[in] X vector [x] +!> @param[in] Y vector [y] +!> @param[out] S solution ( [x]^T*[y] ) + SUBROUTINE s_ddot(n,x,y,s) + IMPLICIT NONE +! N : length of all vector x,y + INTEGER n +! vectors [x], [y] + DOUBLE PRECISION x(n), y(n), s + DOUBLE PRECISION qddot + EXTERNAL qddot + DOUBLE PRECISION ddot + EXTERNAL ddot + +! compute local-sum +#ifdef USE_QDDOT + s = qddot(n,x,1,y,1) +#else + s = ddot(n,x,1,y,1) +#endif + RETURN + END + +!> @brief 2x compute ([x]^T*[y]) distributed and build a global sum, (OpenMP version) +!> @param[in] N length of all vectors +!> @param[in] X vector [x] +!> @param[in] X2 vector [x] +!> @param[in] Y vector [y] +!> @param[in] Y2 vector [y] +!> @param[in] sh_help openmp-shared vector [# threads *2] +!> @param[out] S solution ( [x]^T*[y] ) +!> @param[out] S2 solution ( [x]^T*[y] ) +!> @details +!> Function : compute ([x]^T*[y]) distributed and build a global sum,\n +!> 2 products at once\n + SUBROUTINE omp_2ddot(n,x,y,s,x2,y2,s2,sh_help) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vector x,y + INTEGER n +! lsum : local-summary +! lsum : source summary +! vectors [x], [y] + DOUBLE PRECISION lsum(2), slsum(2), sh_help(*) + DOUBLE PRECISION x(max(n,1)), y(max(n,1)), s + DOUBLE PRECISION x2(max(n,1)), y2(max(n,1)), s2 + INTEGER von, bis + DOUBLE PRECISION qddot + EXTERNAL qddot + DOUBLE PRECISION ddot + EXTERNAL ddot + + lsum(1) = 0.0D0 + lsum(2) = 0.0D0 +! blocking + DO von = 1, n, int(bl_size/bldiv_dot(1)) + bis = min(n,von+int(bl_size/bldiv_dot(1))-1) +! compute local-sum +#ifdef USE_QDDOT + lsum(1) = lsum(1) + qddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + qddot(bis-von+1,x2(von),1,y2(von),1) +#else + lsum(1) = lsum(1) + ddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + ddot(bis-von+1,x2(von),1,y2(von),1) +#endif + END DO +! compute global sum (OpenMP) + CALL xsum_0(2,lsum,slsum,sh_help) + s = slsum(1) + s2 = slsum(2) + RETURN + END + +!> @brief 3x compute ([x]^T*[y]) distributed and build a global sum, (OpenMP version) +!> @param[in] N length of all vectors +!> @param[in] X vector [x] +!> @param[in] X2 vector [x] +!> @param[in] X3 vector [x] +!> @param[in] Y vector [y] +!> @param[in] Y2 vector [y] +!> @param[in] Y3 vector [y] +!> @param[in] sh_help openmp-shared vector [# threads *3] +!> @param[out] S solution ( [x]^T*[y] ) +!> @param[out] S2 solution ( [x]^T*[y] ) +!> @param[out] S3 solution ( [x]^T*[y] ) +!> @details +!> Function : compute ([x]^T*[y]) distributed and build a global sum,\n +!> 3 products at once\n + SUBROUTINE omp_3ddot(n,x,y,s,x2,y2,s2,x3,y3,s3,sh_help) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vector x,y + INTEGER n +! lsum : local-summary +! lsum : source summary +! vectors [x], [y] + DOUBLE PRECISION lsum(3), slsum(3), sh_help(*) + DOUBLE PRECISION x(max(n,1)), y(max(n,1)), s + DOUBLE PRECISION x2(max(n,1)), y2(max(n,1)), s2 + DOUBLE PRECISION x3(max(n,1)), y3(max(n,1)), s3 + INTEGER von, bis + DOUBLE PRECISION qddot + EXTERNAL qddot + DOUBLE PRECISION ddot + EXTERNAL ddot + + lsum(1) = 0.0D0 + lsum(2) = 0.0D0 + lsum(3) = 0.0D0 +! blocking + DO von = 1, n, int(bl_size/bldiv_dot(2)) + bis = min(n,von+int(bl_size/bldiv_dot(2))-1) +! compute local-sum +#ifdef USE_QDDOT + lsum(1) = lsum(1) + qddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + qddot(bis-von+1,x2(von),1,y2(von),1) + lsum(3) = lsum(3) + qddot(bis-von+1,x3(von),1,y3(von),1) +#else + lsum(1) = lsum(1) + ddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + ddot(bis-von+1,x2(von),1,y2(von),1) + lsum(3) = lsum(3) + ddot(bis-von+1,x3(von),1,y3(von),1) +#endif + END DO +! compute global sum (OpenMP) + CALL xsum_0(3,lsum,slsum,sh_help) + s = slsum(1) + s2 = slsum(2) + s3 = slsum(3) + RETURN + END + +!> @brief 4x compute ([x]^T*[y]) distributed and build a global sum, (OpenMP version) +!> @param[in] N length of all vectors +!> @param[in] X vector [x] +!> @param[in] X2 vector [x] +!> @param[in] X3 vector [x] +!> @param[in] X4 vector [x] +!> @param[in] Y vector [y] +!> @param[in] Y2 vector [y] +!> @param[in] Y3 vector [y] +!> @param[in] Y4 vector [y] +!> @param[in] sh_help openmp-shared vector [# threads *4] +!> @param[out] S solution ( [x]^T*[y] ) +!> @param[out] S2 solution ( [x]^T*[y] ) +!> @param[out] S3 solution ( [x]^T*[y] ) +!> @param[out] S4 solution ( [x]^T*[y] ) +!> @details +!> Function : compute ([x]^T*[y]) distributed and build a global sum,\n +!> 4 products at once\n + SUBROUTINE omp_4ddot(n,x,y,s,x2,y2,s2,x3,y3,s3,x4,y4,s4,sh_help) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vector x,y + INTEGER n +! lsum : local-summary +! lsum : source summary, don't do that +! vectors [x], [y] + DOUBLE PRECISION lsum(4), slsum(4), sh_help(*) + DOUBLE PRECISION x(max(n,1)), y(max(n,1)), s + DOUBLE PRECISION x2(max(n,1)), y2(max(n,1)), s2 + DOUBLE PRECISION x3(max(n,1)), y3(max(n,1)), s3 + DOUBLE PRECISION x4(max(n,1)), y4(max(n,1)), s4 + INTEGER von, bis + DOUBLE PRECISION qddot + EXTERNAL qddot + DOUBLE PRECISION ddot + EXTERNAL ddot + + lsum(1) = 0.0D0 + lsum(2) = 0.0D0 + lsum(3) = 0.0D0 + lsum(4) = 0.0D0 +! blocking + DO von = 1, n, int(bl_size/bldiv_dot(3)) + bis = min(n,von+int(bl_size/bldiv_dot(3))-1) +! compute local-sum +#ifdef USE_QDDOT + lsum(1) = lsum(1) + qddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + qddot(bis-von+1,x2(von),1,y2(von),1) + lsum(3) = lsum(3) + qddot(bis-von+1,x3(von),1,y3(von),1) + lsum(4) = lsum(4) + qddot(bis-von+1,x4(von),1,y4(von),1) +#else + lsum(1) = lsum(1) + ddot(bis-von+1,x(von),1,y(von),1) + lsum(2) = lsum(2) + ddot(bis-von+1,x2(von),1,y2(von),1) + lsum(3) = lsum(3) + ddot(bis-von+1,x3(von),1,y3(von),1) + lsum(4) = lsum(4) + ddot(bis-von+1,x4(von),1,y4(von),1) +#endif + END DO +! compute global sum (OpenMP) + CALL xsum_0(4,lsum,slsum,sh_help) + s = slsum(1) + s2 = slsum(2) + s3 = slsum(3) + s4 = slsum(4) + RETURN + END diff --git a/solve/omp_gen_solve.f90 b/solve/omp_gen_solve.f90 new file mode 100644 index 0000000..eca3343 --- /dev/null +++ b/solve/omp_gen_solve.f90 @@ -0,0 +1,207 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], BICGSTAB algorithm based +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is general Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_gen_solve(n_i,n_j,n_k,x,b,r0_hat,depsilon, & + mbc_mask,max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm, & + ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tpos, tanz + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION r0_hat(n_i*n_j*n_k), res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_BiCGStab stuff +! work : control variable : what is to do in this subroutine, +! see more discription in 'pre_bicgstab.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria + + ! INTEGER l, wieviele + ! DOUBLE PRECISION dmaxi, dmini, durchs +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1)& +!$OMP default(shared)& +!$OMP private(tanz,tpos,iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 5 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! preload ([M]x[x]) in [z] + CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,z),ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +10 CONTINUE + + +! BiCGStab routine + CALL pre_bicgstab(tanz,x(tpos),b(tpos),r0_hat(tpos),n, & + loctmp(tpos,1),depsilon,dnrm(tpos),max_it,criteria,res0, & + work,ipar,rpar,lpar) +! impliciete barrier here + +! preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[M]x[y] + IF ((work==do_y_p_v) .OR. (work==more_y_p_v)) THEN +! left precond. + CALL myprco(n,loctmp(1,p),loctmp(1,t_pc)) +! right precond. + CALL myprco(n,loctmp(1,t_pc),loctmp(1,y)) +!$OMP barrier + + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,y),loctmp(1,v),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + END IF + +! [z]:=[M]x[x], for advanced precision + IF (work==more_y_p_v) CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,z), & + ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +! preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[M]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + IF (work==do_z_s_t) THEN +! left precond. + CALL myprco(n,loctmp(1,s),loctmp(1,s_pc)) +! right precond. + CALL myprco(n,loctmp(1,s_pc),loctmp(1,z)) +!$OMP barrier + + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,z),loctmp(1,t),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + +! left precond. + CALL myprco(n,loctmp(1,t),loctmp(1,t_pc)) +!$OMP barrier + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!$OMP end parallel + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_gen_solve_diag.f90 b/solve/omp_gen_solve_diag.f90 new file mode 100644 index 0000000..2de7c20 --- /dev/null +++ b/solve/omp_gen_solve_diag.f90 @@ -0,0 +1,208 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], BICGSTAB algorithm based with Diagonal preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is general Matrix, only used in 'omp_MVP'\n +!> Technics :\n +! - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_gen_solve_diag(n_i,n_j,n_k,x,b,r0_hat,depsilon, & + mbc_mask,max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm, & + ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tpos, tanz + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION r0_hat(n_i*n_j*n_k), res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_BiCGStab stuff +! work : control variable : what is to do in this subroutine, +! see more discription in 'pre_bicgstab.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria + + ! INTEGER l, wieviele + ! DOUBLE PRECISION dmaxi, dmini, durchs +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1)& +!$OMP default(shared)& +!$OMP private(tanz,tpos, iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 5 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +! allocate(rpar(5 +4 *OMP_GET_NUM_of_THREADS())) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! preload ([M]x[x]) in [z] + CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,z),ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +10 CONTINUE + + +! BiCGStab routine + CALL pre_bicgstab(tanz,x(tpos),b(tpos),r0_hat(tpos),n, & + loctmp(tpos,1),depsilon,dnrm(tpos),max_it,criteria,res0, & + work,ipar,rpar,lpar) +! impliciete barrier here + +! preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[M]x[y] + IF ((work==do_y_p_v) .OR. (work==more_y_p_v)) THEN +! left precond. + CALL diagprco(n,md,loctmp(1,p),loctmp(1,t_pc)) +! right precond. + CALL myprco(n,loctmp(1,t_pc),loctmp(1,y)) +!$OMP barrier + + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,y),loctmp(1,v),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + END IF + +! [z]:=[M]x[x], for advanced precision + IF (work==more_y_p_v) CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,z), & + ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +! preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[M]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + IF (work==do_z_s_t) THEN +! left precond. + CALL diagprco(n,md,loctmp(1,s),loctmp(1,s_pc)) +! right precond. + CALL myprco(n,loctmp(1,s_pc),loctmp(1,z)) +!$OMP barrier + + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,z),loctmp(1,t),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + +! left precond. + CALL diagprco(n,md,loctmp(1,t),loctmp(1,t_pc)) +!$OMP barrier + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!$OMP end parallel + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_gen_solve_ilu.f90 b/solve/omp_gen_solve_ilu.f90 new file mode 100644 index 0000000..058e9a6 --- /dev/null +++ b/solve/omp_gen_solve_ilu.f90 @@ -0,0 +1,326 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], BICGSTAB algorithm based with ILU preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[in] UD helper diagonal elements for preconditioning +!> @param[out] bound_block boundary exchange buffer for each block, between the threads +!> @param[out] dnrm normalisation vector, temporary use +!> @param[out] lMA temporary thread local elements of the 1. diagonal of [M] +!> @param[out] lMB temporary thread local elements of the 2. diagonal of [M] +!> @param[out] lMC temporary thread local elements of the 3. diagonal of [M] +!> @param[out] lMD temporary thread local elements of the 4. diagonal of [M] +!> @param[out] lME temporary thread local elements of the 5. diagonal of [M] +!> @param[out] lMF temporary thread local elements of the 6. diagonal of [M] +!> @param[out] lMG temporary thread local elements of the 7. diagonal of [M] +!> @param[out] lUD temporary thread local elements of the helper diagonal [UD] +!> @param[out] lx temporary thread local elements of the solution vector [x] +!> @param[out] lb temporary thread local elements of the right side [b] +!> @param[out] lr0_hat temporary thread local elements of the random vector [r0_hat] +!> @param[out] ldnrm temporary thread local elements of the normalisation vector +!> @param[out] llocTMP temporary thread local elements of the local temporary vectors +!> @param[out] ud_block block buffer for helper diagonal [UD] +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is general Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_gen_solve_ilu(n_i,n_j,n_k,x,b,r0_hat,depsilon, & + mbc_mask,max_it,criteria,ma,mb,mc,md,me,mf,mg,ud, & + bound_block,dnrm,lma,lmb,lmc,lmd,lme,lmf,lmg,lud,lx,lb, & + lr0_hat,ldnrm,lloctmp,ud_block,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N_I*N_J*N_K : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER n_i, n_j, n_k, max_it, ismpl + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION r0_hat(n_i*n_j*n_k), res0, ud(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k) + DOUBLE PRECISION mc(n_i*n_j*n_k), md(n_i*n_j*n_k) + DOUBLE PRECISION me(n_i*n_j*n_k), mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + CHARACTER mbc_mask(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + +! global buffer for boundary exchange + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + DOUBLE PRECISION bound_block(block_i*block_j+block_i*block_k+block_j*block_k,bdim_i,bdim_j,bdim_k,2) +! private copy for preconditioning + DOUBLE PRECISION lma(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lmb(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lmc(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lmd(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lme(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lmf(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lmg(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lud(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lx(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lb(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lr0_hat(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION ldnrm(max_blocks*block_i*block_j*block_k, tlevel_1) + DOUBLE PRECISION lloctmp(max_blocks*block_i*block_j*block_k, max_loctmp,tlevel_1) + DOUBLE PRECISION ud_block(block_i*block_j+block_i*block_k+block_j*block_k,max_blocks,tlevel_1) + +! x,y,z-grid index for each block position + INTEGER, ALLOCATABLE :: xyz_block(:,:) + INTEGER lxyz_block, tid + +! Pre_BiCGStab stuff +! work : control variable : what is to do in this subroutine, +! see more discription in 'pre_bicgstab.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon, summ + + INTEGER xi, yi, zi, loc_mem, loc_memm1 + INTEGER criteria, i, j, k, fkt_proza + EXTERNAL fkt_proza +! openmp-private variables + INTEGER tpos, tanz +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + INTEGER, ALLOCATABLE :: proza_lock(:,:,:) + LOGICAL lpar(1) + + +! start values + work = start + res0 = 1.D+99 + + ALLOCATE(proza_lock(bdim_i,bdim_j,bdim_k)) +! init + CALL set_ival(5,0,ipar) + CALL par_reset(proza_lock) + lpar(1) = .FALSE. + +!$OMP parallel & +!$OMP num_threads(Tlevel_1) & +!$OMP default(none) shared(Tlevel_1,ismpl) & +!$OMP shared(block_i,block_j,block_k, bdim_i,bdim_j,bdim_k,ipar,rpar) & +!$OMP shared(N_I,N_J,N_K, depsilon, max_It, criteria, res0, work,lpar) & +!$OMP shared(bound_block,MA,MB,MC,MD,ME,MF,MG,UD,x,b,r0_hat,ProzA_lock) & +!$OMP shared(mbc_mask, dnrm, ud_block, ldnrm, max_blocks) & +!$OMP shared(lMA,lMB,lMC,lMD,lUD,lME,lMF,lMG,lx,lb,lr0_hat,llocTMP) & +!$OMP private(i,j,k, tid, loc_mem,loc_memm1, lxyz_block, xyz_block) & +!$OMP private(xi,yi,zi,summ,iii, tpos, tanz) +!$ call omp_binding(ismpl) + + CALL omp_part(n_i*n_j*n_k,tpos,tanz) + tid = omp_get_his_thread_num() + 1 + +!$OMP master +! how many entries ? + iii = 5 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier +! init ILU(0)-preconditioner, other start values + CALL prepare_ilu(n_i,n_j,n_k,ma,mb,mc,md,me,mf,mg,ud) + +! max number of private blocks = bdim_i*bdim_j*bdim_k + ALLOCATE(xyz_block(3,bdim_i*bdim_j*bdim_k)) + + lxyz_block = 0 + DO k = 1, bdim_k + DO j = 1, bdim_j + DO i = 1, bdim_i + IF (fkt_proza(i,j,k)==tid-1) THEN +! compute number of private blocks + lxyz_block = lxyz_block + 1 +! setup index information for each private block + xyz_block(1,lxyz_block) = i + xyz_block(2,lxyz_block) = j + xyz_block(3,lxyz_block) = k + END IF + END DO + END DO + END DO +! memory requirements + loc_mem = lxyz_block*block_i*block_j*block_k + loc_memm1 = max_blocks*block_i*block_j*block_k + +! make private copies from the global arrays +!$OMP barrier + CALL lcopy_ilu(n_i,n_j,n_k,ma,lma(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mb,lmb(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mc,lmc(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,md,lmd(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,ud,lud(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,me,lme(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mf,lmf(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mg,lmg(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,x,lx(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,b,lb(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,dnrm,ldnrm(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,r0_hat,lr0_hat(1,tid),lxyz_block,xyz_block) +! lcopy_ilu of [locTMP] not needed, but of the cleanup +!aw-test Call set_dval(loC_memm1*max_loCTMP,0.d0,lloCTMP(1,1,tid)) + +! copy private [UD] surface (position-1) + DO i = 1, lxyz_block + CALL lsurf_ilu(n_i,n_j,n_k,i,ud,ud_block(1,i,tid),lxyz_block,xyz_block) + END DO + + +! INIT +! preload ([M]x[x]) in [z] + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lx(1,tid), & + lloctmp(1,z,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + +!************************************************************** + +10 CONTINUE + +! BiCGStab routine + CALL pre_bicgstab(loc_mem,lx(1,tid),lb(1,tid),lr0_hat(1,tid), & + loc_memm1,lloctmp(1,1,tid),depsilon,ldnrm(1,tid),max_it, & + criteria,res0,work,ipar,rpar,lpar) +! implicit barrier here + +! preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[M]x[y] + IF ((work==do_y_p_v) .OR. (work==more_y_p_v)) THEN +! left precond. + CALL omp_lu_solve2(n_i,n_j,n_k,lxyz_block,lloctmp(1,p,tid), & + lloctmp(1,t_pc,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lud(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid), & + ud_block(1,1,tid),bound_block,xyz_block,proza_lock) +! needs barrier here, [LU] and [MVP] modify "bound_block" +!$OMP barrier +! right precond. +! : call myPrCo(N,locTMP(1,t_pc),locTMP(1,y)) + CALL dcopy(loc_mem,lloctmp(1,t_pc,tid),1,lloctmp(1,y,tid),1) +! MVP + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lloctmp(1,y,tid), & + lloctmp(1,v,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + END IF + +! [z]:=[M]x[x], for advanced precision + IF (work==more_y_p_v) THEN +! needs barrier here, both [MVP] calls modify "bound_block" +!$OMP barrier + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lx(1,tid), & + lloctmp(1,z,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + END IF + +! preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[M]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + IF (work==do_z_s_t) THEN +! left precond. + CALL omp_lu_solve2(n_i,n_j,n_k,lxyz_block,lloctmp(1,s,tid), & + lloctmp(1,s_pc,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lud(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid), & + ud_block(1,1,tid),bound_block,xyz_block,proza_lock) +! needs barrier here, [LU] and [MVP] modify "bound_block" +!$OMP barrier +! right precond. +! : call myPrCo(N,locTMP(1,s_pc),locTMP(1,z)) + CALL dcopy(loc_mem,lloctmp(1,s_pc,tid),1,lloctmp(1,z,tid),1) +! MVP + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lloctmp(1,z,tid), & + lloctmp(1,t,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) +! needs barrier here, [MVP] and [LU] modify "bound_block" +!$OMP barrier +! left precond. + CALL omp_lu_solve2(n_i,n_j,n_k,lxyz_block,lloctmp(1,t,tid), & + lloctmp(1,t_pc,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lud(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid), & + ud_block(1,1,tid),bound_block,xyz_block,proza_lock) + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!************************************************************** + + +! get the global [x] from private + CALL lcopy_bak_ilu(n_i,n_j,n_k,x,lx(1,tid),lxyz_block,xyz_block) + + DEALLOCATE(xyz_block) + +!$OMP end parallel + DEALLOCATE(rpar) + DEALLOCATE(proza_lock) + + RETURN + END diff --git a/solve/omp_gen_solve_ssor.f90 b/solve/omp_gen_solve_ssor.f90 new file mode 100644 index 0000000..2b77f56 --- /dev/null +++ b/solve/omp_gen_solve_ssor.f90 @@ -0,0 +1,225 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], BICGSTAB algorithm based with SSOR preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is general Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_gen_solve_ssor(n_i,n_j,n_k,x,b,r0_hat,depsilon, & + mbc_mask,max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm, & + ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tpos, tanz + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION r0_hat(n_i*n_j*n_k), res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_BiCGStab stuff +! work : control variable : what is to do in this subroutine, +! see more discription in 'pre_bicgstab.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1) & +!$OMP default(shared) & +!$OMP private(tanz,tpos,iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 5 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +! allocate(rpar(5 +4 *OMP_GET_NUM_of_THREADS())) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! ###################### not parallel Code !!! ######################### +! prepare [b^] from [b] +! [b^] = D*(D+L)^(-1) * [b] + CALL ddl(n_i,n_j,n_k,b,loctmp(1,b_hat),ma,mb,mc,md) +! implicit barrier here + +! prepare [r0~] from [r0^] +! [r0~] = D*(D+L)^(-1) * [r0^] + CALL ddl(n_i,n_j,n_k,r0_hat,loctmp(1,r0_tilde),ma,mb,mc,md) +! implicit barrier here +! ################### above not parallel Code !!! ###################### + +! preload ([M]x[x]) in [z] + CALL ssor_mvp_single(n_i,n_j,n_k,x,loctmp(1,z),loctmp(1,mt), & + ma,mb,mc,md,me,mf,mg) +! implicit barrier here + + +10 CONTINUE + + +! BiCGStab routine + CALL pre_bicgstab(tanz,x(tpos),loctmp(tpos,b_hat), & + loctmp(tpos,r0_tilde),n,loctmp(tpos,1),depsilon,dnrm(tpos), & + max_it,criteria,res0,work,ipar,rpar,lpar) +! implicit barrier here + +! preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[M]x[y] + IF ((work==do_y_p_v) .OR. (work==more_y_p_v)) THEN +! Left precond. + CALL myprco(n,loctmp(1,p),loctmp(1,t_pc)) +! Right precond. + CALL myprco(n,loctmp(1,t_pc),loctmp(1,y)) +!$OMP barrier + + CALL ssor_mvp_single(n_i,n_j,n_k,loctmp(1,y),loctmp(1,v), & + loctmp(1,mt),ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + END IF + +! [z]:=[M]x[x], for advanced precision + IF (work==more_y_p_v) CALL ssor_mvp_single(n_i,n_j,n_k,x, & + loctmp(1,z),loctmp(1,mt),ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +! preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[M]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + IF (work==do_z_s_t) THEN +! Left precond. + CALL myprco(n,loctmp(1,s),loctmp(1,s_pc)) +! Right precond. + CALL myprco(n,loctmp(1,s_pc),loctmp(1,z)) +!$OMP barrier + + CALL ssor_mvp_single(n_i,n_j,n_k,loctmp(1,z),loctmp(1,t), & + loctmp(1,mt),ma,mb,mc,md,me,mf,mg) +! implicit barrier here + +! Left precond. + CALL myprco(n,loctmp(1,t),loctmp(1,t_pc)) +!$OMP barrier + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!$OMP end parallel + +! ###################### not parallel Code !!! ######################### +! compute [x] +! [x] = (D+U)^(-1) * [x^] + CALL du(n_i,n_j,n_k,x,x,md,me,mf,mg) +! ################### above not parallel Code !!! ###################### + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_mvp.f90 b/solve/omp_mvp.f90 new file mode 100644 index 0000000..bd676fb --- /dev/null +++ b/solve/omp_mvp.f90 @@ -0,0 +1,345 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief apply 7point-star matrix multiply [as]:=[M]x[s], (OpenMP version) +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in] s vector [s] +!> @param[out] as vector [as] +!> @param[in] A 1. diagonal of the system matrix [M] +!> @param[in] B 2. diagonal of the system matrix [M] +!> @param[in] C 3. diagonal of the system matrix [M] +!> @param[in] D 4. (main) diagonal of the system matrix [M] +!> @param[in] E 5. diagonal of the system matrix [M] +!> @param[in] F 6. diagonal of the system matrix [M] +!> @param[in] G 7. diagonal of the system matrix [M] +!> @details +!> OpenMP parallelised, general version - no special blocking\n +!> apply 7point-star matrix multiply\n +!> compute [as]:=[M]x[s], [s],[as],[M] given in 3-D-structure\n +!> Data-Cube :\n +!> @image html cube.png +! k * * * * +! / * * * +! 0 -j * * * * * +! | * * * +! i * * * +! * * * * + SUBROUTINE omp_mvp(n_i,n_j,n_k,s,as,a,b,c,d,e,f,g) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + + INTEGER n_i, n_j, n_k +! use mod_blocking_size + + DOUBLE PRECISION s(*), as(*) + DOUBLE PRECISION a(*), b(*), c(*), d(*), e(*), f(*), g(*) + + INTEGER pim, pip, pjm, pjp, pkm, pkp + INTEGER aim, aip, ajm, ajp, akm, akp + INTEGER bm, pm, pmb, am, pmmax + +! thread stuff + INTEGER tpos, tanz + + + tpos = 1 + tanz = n_i*n_j*n_k +!$ call OMP_PART(N_I*N_J*N_K,tpos,tanz) + + bm = tpos + tanz - 1 + pm = tpos + pmmax = n_i*n_j*n_k + 1 + + +! not ready yet, should modify for better performance ! +! +2.5% for '/27' + pmb = min(pm+int(bl_size/bldiv_mvp),bm+1) + am = pmb - pm + +! I-dim + pim = max(pm-1,1) + aim = pmb - 1 - pim + pip = min(pmb+1,pmmax) + aip = pip - 1 - pm + +! J-dim + pjm = max(pm-n_i,1) + ajm = pmb - n_i - pjm + pjp = min(pmb+n_i,pmmax) + ajp = pjp - n_i - pm + +! K-dim + pkm = max(pm-n_i*n_j,1) + akm = pmb - n_i*n_j - pkm + pkp = min(pmb+n_i*n_j,pmmax) + akp = pkp - n_i*n_j - pm + +100 CONTINUE + + CALL dxyz(am,s(pm),d(pm),as(pm)) +!AW C$OMP barrier + + IF (n_i>1) THEN + CALL dxypz(aip,s(pm+1),e(pm),as(pm)) +!AW C$OMP barrier + END IF + IF (n_j>1) THEN + CALL dxypz(ajp,s(pm+n_i),f(pm),as(pm)) +!AW C$OMP barrier + END IF + IF (n_k>1) THEN + CALL dxypz(akp,s(pm+n_i*n_j),g(pm),as(pm)) +!AW C$OMP barrier + END IF + + IF (n_i>1) THEN + CALL dxypz(aim,s(pim),c(pim+1),as(pim+1)) +!AW C$OMP barrier + END IF + IF (n_j>1) THEN + CALL dxypz(ajm,s(pjm),b(pjm+n_i),as(pjm+n_i)) +!AW C$OMP barrier + END IF + IF (n_k>1) THEN + CALL dxypz(akm,s(pkm),a(pkm+n_i*n_j),as(pkm+n_i*n_j)) +!AW C$OMP barrier + END IF + +!aw write(*,*)' ',OMP_GET_HIS_THREAD_NUM(),pm,pm+am-1,pmb-1 +!aw write(*,*)'iC',OMP_GET_HIS_THREAD_NUM(),pim+1,-1,aim +!aw write(*,*)'iE',OMP_GET_HIS_THREAD_NUM(),pm,1,aip +!aw write(*,*)'jB',OMP_GET_HIS_THREAD_NUM(),pjm+N_I,-N_I,ajm +!aw write(*,*)'jF',OMP_GET_HIS_THREAD_NUM(),pm,N_I,ajp +!aw write(*,*)'kA',OMP_GET_HIS_THREAD_NUM(),pkm+N_I*N_J,-N_I*N_J,akm +!aw write(*,*)'kG',OMP_GET_HIS_THREAD_NUM(),pm,N_I*N_J,akp + + pm = pmb + pmb = min(pm+int(bl_size/bldiv_mvp),bm+1) + am = pmb - pm + +! I-dim + pim = max(pm-1,1) + aim = pmb - 1 - pim + pip = min(pmb+1,pmmax) + aip = pip - 1 - pm + +! J-dim + pjm = max(pm-n_i,1) + ajm = pmb - n_i - pjm + pjp = min(pmb+n_i,pmmax) + ajp = pjp - n_i - pm + +! K-dim + pkm = max(pm-n_i*n_j,1) + akm = pmb - n_i*n_j - pkm + pkp = min(pmb+n_i*n_j,pmmax) + akp = pkp - n_i*n_j - pm + + IF (am>0) GO TO 100 + +!$OMP barrier +! need barrier here + + RETURN + END + +!> @brief apply 7point-star matrix multiply [as]:=[M]x[s], serial (no OpenMP) implementation +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in] s vector [s] +!> @param[out] as vector [as] +!> @param[in] A 1. diagonal of the system matrix [M] +!> @param[in] B 2. diagonal of the system matrix [M] +!> @param[in] C 3. diagonal of the system matrix [M] +!> @param[in] D 4. (main) diagonal of the system matrix [M] +!> @param[in] E 5. diagonal of the system matrix [M] +!> @param[in] F 6. diagonal of the system matrix [M] +!> @param[in] G 7. diagonal of the system matrix [M] +!> @details +!> serial (not OpenMP parallelised), general version - no special blocking\n +!> apply 7point-star matrix multiply\n +!> compute [as]:=[M]x[s], [s],[as],[M] given in 3-D-structure\n +!> Data-Cube :\n +!> @image html cube.png +! k * * * * +! / * * * +! 0 -j * * * * * +! | * * * +! i * * * +! * * * * + SUBROUTINE s_mvp(n_i,n_j,n_k,s,as,a,b,c,d,e,f,g) + use mod_blocking_size + IMPLICIT NONE + + INTEGER n_i, n_j, n_k +! use mod_blocking_size + + DOUBLE PRECISION s(*), as(*) + DOUBLE PRECISION a(*), b(*), c(*), d(*), e(*), f(*), g(*) + + INTEGER pim, pip, pjm, pjp, pkm, pkp + INTEGER aim, aip, ajm, ajp, akm, akp + INTEGER bm, pm, pmb, am, pmmax + +! thread stuff (disabled here) + INTEGER tpos, tanz + + + tpos = 1 + tanz = n_i*n_j*n_k + + bm = tpos + tanz - 1 + pm = tpos + pmmax = n_i*n_j*n_k + 1 + +! not ready yet, should modify for better performance ! +! +2.5% for '/27' + pmb = min(pm+int(bl_size/bldiv_mvp),bm+1) + am = pmb - pm + +! I-dim + pim = max(pm-1,1) + aim = pmb - 1 - pim + pip = min(pmb+1,pmmax) + aip = pip - 1 - pm + +! J-dim + pjm = max(pm-n_i,1) + ajm = pmb - n_i - pjm + pjp = min(pmb+n_i,pmmax) + ajp = pjp - n_i - pm + +! K-dim + pkm = max(pm-n_i*n_j,1) + akm = pmb - n_i*n_j - pkm + pkp = min(pmb+n_i*n_j,pmmax) + akp = pkp - n_i*n_j - pm + +100 CONTINUE + + CALL dxyz(am,s(pm),d(pm),as(pm)) + + IF (n_i>1) THEN + CALL dxypz(aip,s(pm+1),e(pm),as(pm)) + END IF + IF (n_j>1) THEN + CALL dxypz(ajp,s(pm+n_i),f(pm),as(pm)) + END IF + IF (n_k>1) THEN + CALL dxypz(akp,s(pm+n_i*n_j),g(pm),as(pm)) + END IF + + IF (n_i>1) THEN + CALL dxypz(aim,s(pim),c(pim+1),as(pim+1)) + END IF + IF (n_j>1) THEN + CALL dxypz(ajm,s(pjm),b(pjm+n_i),as(pjm+n_i)) + END IF + IF (n_k>1) THEN + CALL dxypz(akm,s(pkm),a(pkm+n_i*n_j),as(pkm+n_i*n_j)) + END IF + + pm = pmb + pmb = min(pm+int(bl_size/bldiv_mvp),bm+1) + am = pmb - pm + +! I-dim + pim = max(pm-1,1) + aim = pmb - 1 - pim + pip = min(pmb+1,pmmax) + aip = pip - 1 - pm + +! J-dim + pjm = max(pm-n_i,1) + ajm = pmb - n_i - pjm + pjp = min(pmb+n_i,pmmax) + ajp = pjp - n_i - pm + +! K-dim + pkm = max(pm-n_i*n_j,1) + akm = pmb - n_i*n_j - pkm + pkp = min(pmb+n_i*n_j,pmmax) + akp = pkp - n_i*n_j - pm + + IF (am>0) GO TO 100 + + RETURN + END + +!> @brief BLAS adapting : z=z+x*y +!> @param[in] N length of vectors [z],[x],[y] +!> @param[in] x vector [x] +!> @param[in] y vector [y] +!> @param[in] z vector [z] +!> @param[out] z vector [z] + SUBROUTINE dxypz(n,x,y,z) + IMPLICIT NONE + INTEGER n, i, m + DOUBLE PRECISION x(n), y(n), z(n) + + m = mod(n,4) + DO i = 1, m + z(i) = z(i) + x(i)*y(i) + END DO + + m = m + 1 + DO i = m, n, 4 + z(i+0) = z(i+0) + x(i+0)*y(i+0) + z(i+1) = z(i+1) + x(i+1)*y(i+1) + z(i+2) = z(i+2) + x(i+2)*y(i+2) + z(i+3) = z(i+3) + x(i+3)*y(i+3) + END DO + + RETURN + END + + +!> @brief BLAS adapting : z=x*y +!> @param[in] N length of vectors [z],[x],[y] +!> @param[in] x vector [x] +!> @param[in] y vector [y] +!> @param[out] z vector [z] + SUBROUTINE dxyz(n,x,y,z) + IMPLICIT NONE + INTEGER n, i, m + DOUBLE PRECISION x(n), y(n), z(n) + + m = mod(n,4) + DO i = 1, m + z(i) = x(i)*y(i) + END DO + + m = m + 1 + DO i = m, n, 4 + z(i+0) = x(i+0)*y(i+0) + z(i+1) = x(i+1)*y(i+1) + z(i+2) = x(i+2)*y(i+2) + z(i+3) = x(i+3)*y(i+3) + END DO + + RETURN + END diff --git a/solve/omp_mvp2.f90 b/solve/omp_mvp2.f90 new file mode 100644 index 0000000..adb4f82 --- /dev/null +++ b/solve/omp_mvp2.f90 @@ -0,0 +1,418 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief apply thread local 7point-star matrix multiply [as]:=[M]x[s], (OpenMP version) +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in] lxyz_block number of blocks +!> @param[in] xloc thread local blocks of the vector [s] +!> @param[out] Mxloc thread local blocks of the vector [as] +!> @param[in] LMA thread local blocks of the 1. diagonal of the system matrix [M] +!> @param[in] LMB thread local blocks of the 2. diagonal of the system matrix [M] +!> @param[in] LMC thread local blocks of the 3. diagonal of the system matrix [M] +!> @param[in] LMD thread local blocks of the 4. (main) diagonal of the system matrix [M] +!> @param[in] LME thread local blocks of the 5. diagonal of the system matrix [M] +!> @param[in] LMF thread local blocks of the 6. diagonal of the system matrix [M] +!> @param[in] LMG thread local blocks of the 7. diagonal of the system matrix [M] +!> @param[in] xyz_block block dimensions +!> @param[in] bound_block boundary exchange buffer for each block, between the threads +!> @details +!> OpenMP parallelised with special blocking\n + SUBROUTINE omp_mvp2(n_i,n_j,n_k,lxyz_block,xloc,mxloc,lma,lmb, & + lmc,lmd,lme,lmf,lmg,bound_block,xyz_block) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vectors r,z + INTEGER n_i, n_j, n_k + INTEGER k_e, j_e, i_e + INTEGER ii + INTEGER xi, yi, zi + INTEGER xip1, yip1, zip1, xim1, yim1, zim1 + +! use mod_blocking_size + + INTEGER lxyz_block, xyz_block(3,lxyz_block) + DOUBLE PRECISION lme(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmf(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmg(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmb(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmc(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmd(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lma(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION xloc(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION mxloc(block_i*block_j*block_k,lxyz_block) +! global boundary buffer [x] + DOUBLE PRECISION bound_block(block_i*block_j+block_i*block_k+ & + block_j*block_k,bdim_i,bdim_j,bdim_k,2) + + INTEGER isurf, ijsurf, ijksurf + + +! surface offset: 1=I-dim, isurf=J-dim, ijsurf=K-dim + isurf = block_j*block_k + 1 + ijsurf = isurf + block_i*block_k + ijksurf = block_j*block_k + block_i*block_k + block_i*block_j +! ----------------------------------------------------------------- + +! exchange boundaries of all blocks + DO ii = 1, lxyz_block + xi = xyz_block(1,ii) + yi = xyz_block(2,ii) + zi = xyz_block(3,ii) +! compute begin & end + i_e = min(block_i,n_i-((xi-1)*block_i)) + j_e = min(block_j,n_j-((yi-1)*block_j)) + k_e = min(block_k,n_k-((zi-1)*block_k)) +! block index dim-1 + xim1 = max(xi-1,1) + yim1 = max(yi-1,1) + zim1 = max(zi-1,1) +! block index dim+1 + xip1 = min(xi+1,bdim_i) + yip1 = min(yi+1,bdim_j) + zip1 = min(zi+1,bdim_k) + + CALL exchange_xloc(block_i,block_j,block_k,i_e,j_e,k_e, & + xloc(1,ii),bound_block(1,xim1,yi,zi,2), & + bound_block(isurf,xi,yim1,zi,2),bound_block(ijsurf,xi,yi, & + zim1,2),bound_block(1,xip1,yi,zi,1), & + bound_block(isurf,xi,yip1,zi,1),bound_block(ijsurf,xi,yi, & + zip1,1),bound_block(1,xi,yi,zi,1), & + bound_block(isurf,xi,yi,zi,1),bound_block(ijsurf,xi,yi,zi, & + 1),bound_block(1,xi,yi,zi,2),bound_block(isurf,xi,yi,zi,2) & + ,bound_block(ijsurf,xi,yi,zi,2),xim1-xi+1,yim1-yi+1, & + zim1-zi+1,xip1-xi-1,yip1-yi-1,zip1-zi-1) + END DO + +!$OMP barrier +! MVP of all blocks + DO ii = 1, lxyz_block + xi = xyz_block(1,ii) + yi = xyz_block(2,ii) + zi = xyz_block(3,ii) +! compute begin & end + i_e = min(block_i,n_i-((xi-1)*block_i)) + j_e = min(block_j,n_j-((yi-1)*block_j)) + k_e = min(block_k,n_k-((zi-1)*block_k)) + + CALL mvp_xloc(block_i,block_j,block_k,i_e,j_e,k_e, & + xloc(1,ii),mxloc(1,ii),lma(1,ii),lmb(1,ii),lmc(1,ii), & + lmd(1,ii),lme(1,ii),lmf(1,ii),lmg(1,ii), & + bound_block(1,xi,yi,zi,1),bound_block(isurf,xi,yi,zi,1), & + bound_block(ijsurf,xi,yi,zi,1),bound_block(1,xi,yi,zi,2), & + bound_block(isurf,xi,yi,zi,2),bound_block(ijsurf,xi,yi,zi, & + 2)) + END DO + + RETURN + END + +!> @brief exchange boundary for the [xloc] block +!> @param[in] ldI leading dimensions in I direction +!> @param[in] ldJ leading dimensions in J direction +!> @param[in] ldK leading dimensions in K direction +!> @param[in] i_e block size in I direction +!> @param[in] j_e block size in J direction +!> @param[in] k_e block size in K direction +!> @param[out] xloc_im1 global boundary buffer to the -1 neighbour in I direction +!> @param[out] xloc_jm1 global boundary buffer to the -1 neighbour in J direction +!> @param[out] xloc_km1 global boundary buffer to the -1 neighbour in K direction +!> @param[out] xloc_ip1 global boundary buffer to the +1 neighbour in I direction +!> @param[out] xloc_jp1 global boundary buffer to the +1 neighbour in J direction +!> @param[out] xloc_kp1 global boundary buffer to the +1 neighbour in K direction +!> @param[out] sxloc_im1 (self) own boundary buffer from the -1 neighbour in I direction +!> @param[out] sxloc_jm1 (self) own boundary buffer from the -1 neighbour in J direction +!> @param[out] sxloc_km1 (self) own boundary buffer from the -1 neighbour in K direction +!> @param[out] sxloc_ip1 (self) own boundary buffer from the +1 neighbour in I direction +!> @param[out] sxloc_jp1 (self) own boundary buffer from the +1 neighbour in J direction +!> @param[out] sxloc_kp1 (self) own boundary buffer from the +1 neighbour in K direction +!> @param[in] cmi 0: copy boundary to the -1 neighbour in I direction, <>0: clear local buffer +!> @param[in] cmj 0: copy boundary to the -1 neighbour in J direction, <>0: clear local buffer +!> @param[in] cmk 0: copy boundary to the -1 neighbour in K direction, <>0: clear local buffer +!> @param[in] cpi 0: copy boundary to the +1 neighbour in I direction, <>0: clear local buffer +!> @param[in] cpj 0: copy boundary to the +1 neighbour in J direction, <>0: clear local buffer +!> @param[in] cpk 0: copy boundary to the +1 neighbour in K direction, <>0: clear local buffer +!> @param[in] xloc local block (elements) + SUBROUTINE exchange_xloc(ldi,ldj,ldk,i_e,j_e,k_e,xloc,xloc_im1, & + xloc_jm1,xloc_km1,xloc_ip1,xloc_jp1,xloc_kp1,sxloc_im1, & + sxloc_jm1,sxloc_km1,sxloc_ip1,sxloc_jp1,sxloc_kp1,cmi,cmj, & + cmk,cpi,cpj,cpk) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vectors r,z + INTEGER i_e, j_e, k_e, i, j, k, ldi, ldj, ldk + INTEGER cmi, cmj, cmk, cpi, cpj, cpk +! vectors [r], [z] + DOUBLE PRECISION xloc(ldi,ldj,ldk) + +! use mod_blocking_size +! global boundary buffer + DOUBLE PRECISION xloc_im1(block_j,block_k) + DOUBLE PRECISION xloc_jm1(block_i,block_k) + DOUBLE PRECISION xloc_km1(block_i,block_j) + DOUBLE PRECISION xloc_ip1(block_j,block_k) + DOUBLE PRECISION xloc_jp1(block_i,block_k) + DOUBLE PRECISION xloc_kp1(block_i,block_j) +! (self) owner of this bloCk + DOUBLE PRECISION sxloc_im1(block_j,block_k) + DOUBLE PRECISION sxloc_jm1(block_i,block_k) + DOUBLE PRECISION sxloc_km1(block_i,block_j) + DOUBLE PRECISION sxloc_ip1(block_j,block_k) + DOUBLE PRECISION sxloc_jp1(block_i,block_k) + DOUBLE PRECISION sxloc_kp1(block_i,block_j) + +! boundary exchange +! [2D-I] + IF (cmi==0) THEN + DO k = 1, k_e + DO j = 1, j_e + xloc_im1(j,k) = xloc(1,j,k) + END DO + END DO + ELSE +! own buffer + DO k = 1, k_e + DO j = 1, j_e + sxloc_im1(j,k) = 0.0D0 + END DO + END DO + END IF + IF (cpi==0) THEN + DO k = 1, k_e + DO j = 1, j_e + xloc_ip1(j,k) = xloc(i_e,j,k) + END DO + END DO + ELSE +! own buffer + DO k = 1, k_e + DO j = 1, j_e + sxloc_ip1(j,k) = 0.0D0 + END DO + END DO + END IF + +! [2D-J] + IF (cmj==0) THEN + DO k = 1, k_e + DO i = 1, i_e + xloc_jm1(i,k) = xloc(i,1,k) + END DO + END DO + ELSE +! own buffer + DO k = 1, k_e + DO i = 1, i_e + sxloc_jm1(i,k) = 0.0D0 + END DO + END DO + END IF + IF (cpj==0) THEN + DO k = 1, k_e + DO i = 1, i_e + xloc_jp1(i,k) = xloc(i,j_e,k) + END DO + END DO + ELSE +! own buffer + DO k = 1, k_e + DO i = 1, i_e + sxloc_jp1(i,k) = 0.0D0 + END DO + END DO + END IF + +! [2D-K] + IF (cmk==0) THEN + DO j = 1, j_e + DO i = 1, i_e + xloc_km1(i,j) = xloc(i,j,1) + END DO + END DO + ELSE +! own buffer + DO j = 1, j_e + DO i = 1, i_e + sxloc_km1(i,j) = 0.0D0 + END DO + END DO + END IF + IF (cpk==0) THEN + DO j = 1, j_e + DO i = 1, i_e + xloc_kp1(i,j) = xloc(i,j,k_e) + END DO + END DO + ELSE +! own buffer + DO j = 1, j_e + DO i = 1, i_e + sxloc_kp1(i,j) = 0.0D0 + END DO + END DO + END IF + + RETURN + END + +!> @brief thread local block matrix vector product [as]:=[M]x[s], one single block +!> @param[in] ldI leading dimensions in I direction +!> @param[in] ldJ leading dimensions in J direction +!> @param[in] ldK leading dimensions in K direction +!> @param[in] i_e block size in I direction +!> @param[in] j_e block size in J direction +!> @param[in] k_e block size in K direction +!> @param[in] xloc local block (elements) - thread local part of vector [s] +!> @param[out] Mxloc result vector - thread local part of vector [as] +!> @param[in] MA thread local blocks of the 1. diagonal of the system matrix [M] +!> @param[in] MB thread local blocks of the 2. diagonal of the system matrix [M] +!> @param[in] MC thread local blocks of the 3. diagonal of the system matrix [M] +!> @param[in] MD thread local blocks of the 4. (main) diagonal of the system matrix [M] +!> @param[in] ME thread local blocks of the 5. diagonal of the system matrix [M] +!> @param[in] MF thread local blocks of the 6. diagonal of the system matrix [M] +!> @param[in] MG thread local blocks of the 7. diagonal of the system matrix [M] +!> @param[in] xloc_im1 global boundary buffer from the -1 neighbour in I direction +!> @param[in] xloc_jm1 global boundary buffer from the -1 neighbour in J direction +!> @param[in] xloc_km1 global boundary buffer from the -1 neighbour in K direction +!> @param[in] xloc_ip1 global boundary buffer from the +1 neighbour in I direction +!> @param[in] xloc_jp1 global boundary buffer from the +1 neighbour in J direction +!> @param[in] xloc_kp1 global boundary buffer from the +1 neighbour in K direction + SUBROUTINE mvp_xloc(ldi,ldj,ldk,i_e,j_e,k_e,xloc,mxloc,ma,mb,mc, & + md,me,mf,mg,xloc_im1,xloc_jm1,xloc_km1,xloc_ip1,xloc_jp1, & + xloc_kp1) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vectors r,z + INTEGER i_e, j_e, k_e, i, j, k, ldi, ldj, ldk +! vectors [r], [z] + DOUBLE PRECISION xloc(ldi,ldj,ldk), mxloc(ldi,ldj,ldk) + DOUBLE PRECISION ma(ldi,ldj,ldk), mb(ldi,ldj,ldk) + DOUBLE PRECISION mc(ldi,ldj,ldk), md(ldi,ldj,ldk) + DOUBLE PRECISION me(ldi,ldj,ldk), mf(ldi,ldj,ldk) + DOUBLE PRECISION mg(ldi,ldj,ldk) + +! use mod_blocking_size +! global boundary buffer + DOUBLE PRECISION xloc_im1(block_j,block_k) + DOUBLE PRECISION xloc_jm1(block_i,block_k) + DOUBLE PRECISION xloc_km1(block_i,block_j) + DOUBLE PRECISION xloc_ip1(block_j,block_k) + DOUBLE PRECISION xloc_jp1(block_i,block_k) + DOUBLE PRECISION xloc_kp1(block_i,block_j) + +! [I] direction + i = 1 + DO k = 1, k_e + DO j = 1, j_e + mxloc(i,j,k) = md(i,j,k)*xloc(i,j,k) + & + mc(i,j,k)*xloc_im1(j,k) + END DO + END DO + DO k = 1, k_e + DO j = 1, j_e + DO i = 2, i_e + mxloc(i,j,k) = md(i,j,k)*xloc(i,j,k) + & + mc(i,j,k)*xloc(i-1,j,k) + END DO + END DO + END DO + i = i_e + DO k = 1, k_e + DO j = 1, j_e + mxloc(i,j,k) = mxloc(i,j,k) + me(i,j,k)*xloc_ip1(j,k) + END DO + END DO + DO k = 1, k_e + DO j = 1, j_e + DO i = 1, i_e - 1 + mxloc(i,j,k) = mxloc(i,j,k) + me(i,j,k)*xloc(i+1,j,k) + END DO + END DO + END DO + +! [J] direction + j = 1 + DO k = 1, k_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mb(i,j,k)*xloc_jm1(i,k) + END DO + END DO + DO k = 1, k_e + DO j = 2, j_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mb(i,j,k)*xloc(i,j-1,k) + END DO + END DO + END DO + j = j_e + DO k = 1, k_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mf(i,j,k)*xloc_jp1(i,k) + END DO + END DO + DO k = 1, k_e + DO j = 1, j_e - 1 + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mf(i,j,k)*xloc(i,j+1,k) + END DO + END DO + END DO + +! [K] direction + k = 1 + DO j = 1, j_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + ma(i,j,k)*xloc_km1(i,j) + END DO + END DO + DO k = 2, k_e + DO j = 1, j_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + ma(i,j,k)*xloc(i,j,k-1) + END DO + END DO + END DO + k = k_e + DO j = 1, j_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mg(i,j,k)*xloc_kp1(i,j) + END DO + END DO + DO k = 1, k_e - 1 + DO j = 1, j_e + DO i = 1, i_e + mxloc(i,j,k) = mxloc(i,j,k) + mg(i,j,k)*xloc(i,j,k+1) + END DO + END DO + END DO + + RETURN + END diff --git a/solve/omp_preconditioners.f90 b/solve/omp_preconditioners.f90 new file mode 100644 index 0000000..1253d51 --- /dev/null +++ b/solve/omp_preconditioners.f90 @@ -0,0 +1,1100 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief ILU(0) preconditioner, solving block-based [L][U] x [x] = [b], (OpenMP version) +!> @param[in] N_I lengths of I dimension of local matrix [M]~[L][U] +!> @param[in] N_J lengths of J dimension of local matrix [M]~[L][U] +!> @param[in] N_K lengths of K dimension of local matrix [M]~[L][U] +!> @param[in] lxyz_block number of blocks +!> @param[in] bloc thread local blocks of vector [b] +!> @param[out] xloc thread local blocks of vector [x] +!> @param[in] lMA thread local blocks of the 1. diagonal of [L] +!> @param[in] lMB thread local blocks of the 2. diagonal of [L] +!> @param[in] lMC thread local blocks of the 3. diagonal of [L] +!> @param[in] lUD thread local blocks of the helper diagonal [UD] of [L] and [U] +!> @param[in] lME thread local blocks of the 2. diagonal of [U] +!> @param[in] lMF thread local blocks of the 3. diagonal of [U] +!> @param[in] lMG thread local blocks of the 4. diagonal of [U] +!> @param[out] ud_block block buffer for helper diagonal [UD] +!> @param[out] bound_block boundary exchange buffer for each block, between the threads +!> @param[in] xyz_block block dimensions +!> @param[in,out] ProzA_lock locks to mark alreads computed blocks + SUBROUTINE omp_lu_solve2(n_i,n_j,n_k,lxyz_block,bloc,xloc,lma, & + lmb,lmc,lud,lme,lmf,lmg,ud_block,bound_block,xyz_block, & + proza_lock) + use arrays + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vectors r,z + INTEGER n_i, n_j, n_k + INTEGER k_e, j_e, i_e + INTEGER ii, jj, kk, ll + INTEGER xi, yi, zi + INTEGER xip1, yip1, zip1, xim1, yim1, zim1 +! use mod_blocking_size + INTEGER lxyz_block, xyz_block(3,lxyz_block) + DOUBLE PRECISION lme(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmf(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmg(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmb(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lmc(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lud(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION lma(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION bloc(block_i*block_j*block_k,lxyz_block) + DOUBLE PRECISION xloc(block_i*block_j*block_k,lxyz_block) +! [UD] surface on position-1 + DOUBLE PRECISION ud_block(block_i*block_j+block_i*block_k+ & + block_j*block_k,lxyz_block) +! global boundary buffer [x] + DOUBLE PRECISION bound_block(block_i*block_j+block_i*block_k+ & + block_j*block_k,bdim_i,bdim_j,bdim_k) + + INTEGER proza_lock(bdim_i*bdim_j*bdim_k) + INTEGER par_name, isurf, ijsurf, ijksurf + EXTERNAL par_name + + +! surface offset: 1=I-dim, isurf=J-dim, ijsurf=K-dim + isurf = block_j*block_k + 1 + ijsurf = isurf + block_i*block_k + ijksurf = block_j*block_k + block_i*block_k + block_i*block_j +! ----------------------------------------------------------------- + +! over all local blocks + DO ii = 1, lxyz_block +! 'jj' is the linear block index corresponding [xi,yi,zi] +100 DO jj = 1, lxyz_block + kk = 0 + xi = xyz_block(1,jj) + yi = xyz_block(2,jj) + zi = xyz_block(3,jj) +! [i,j,k]-index + ll = xi + bdim_i*(yi-1) + bdim_i*bdim_j*(zi-1) +! search for locked blocks (needs to be computed) + IF (par_name(proza_lock(ll))==0) THEN +! search for unlocked blocks (already computed) +! test [i-1,j,k] + IF (xi>1) THEN +! [i-1,j,k]-index + xip1 = ll - 1 + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! test [i,j-1,k] + IF (yi>1) THEN +! [i,j-1,k]-index + xip1 = ll - bdim_i + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! test [i,j,k-1] + IF (zi>1) THEN +! [i,j,k-1]-index + xip1 = ll - bdim_i*bdim_j + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! can the block be computed ? + IF (kk==3) THEN +! now: [xi,yi,zi] is the current computable block 'll', private 'jj' + GO TO 101 + END IF + END IF + END DO +! polling ... needs to found a free block + GO TO 100 +! found a computable block +101 CONTINUE + +! compute begin & end + i_e = min(block_i,n_i-((xi-1)*block_i)) + j_e = min(block_j,n_j-((yi-1)*block_j)) + k_e = min(block_k,n_k-((zi-1)*block_k)) +! block index dim+1 + xip1 = min(xi+1,bdim_i) + yip1 = min(yi+1,bdim_j) + zip1 = min(zi+1,bdim_k) + +! solve [L]x[t]=[b] + CALL flu_left2(block_i,block_j,block_k,i_e,j_e,k_e, & + bloc(1,jj),xloc(1,jj),lma(1,jj),lmb(1,jj),lmc(1,jj), & + lud(1,jj),bound_block(1,xi,yi,zi), & + bound_block(isurf,xi,yi,zi),bound_block(ijsurf,xi,yi,zi), & + bound_block(1,xip1,yi,zi),bound_block(isurf,xi,yip1,zi), & + bound_block(ijsurf,xi,yi,zip1),ud_block(1,jj), & + ud_block(isurf,jj),ud_block(ijsurf,jj),xip1-xi-1, & + yip1-yi-1,zip1-zi-1) + + CALL par_disab(proza_lock(ll)) + + IF ((xi==bdim_i) .AND. (yi==bdim_j) .AND. (zi==bdim_k)) THEN + CALL par_reset(proza_lock) + CALL set_dval(ijksurf,0.D0,bound_block(1,xi,yi,zi)) + END IF + + END DO + +! ----------------------------------------------------------------- + +! waiting for finishing L-step +!$OMP barrier + +! ----------------------------------------------------------------- + +! over all local blocks + DO ii = 1, lxyz_block +! 'jj' is the linear block index corresponding [xi,yi,zi] +200 DO jj = lxyz_block, 1, -1 + kk = 0 + xi = xyz_block(1,jj) + yi = xyz_block(2,jj) + zi = xyz_block(3,jj) +! [i,j,k]-index + ll = xi + bdim_i*(yi-1) + bdim_i*bdim_j*(zi-1) +! search for locked blocks (needs to be computed) + IF (par_name(proza_lock(ll))==0) THEN +! search for unlocked blocks (already computed) +! test [i+1,j,k] + IF (xi<bdim_i) THEN +! [i+1,j,k]-index + xip1 = ll + 1 + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! test [i,j+1,k] + IF (yi<bdim_j) THEN +! [i,j+1,k]-index + xip1 = ll + bdim_i + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! test [i,j,k+1] + IF (zi<bdim_k) THEN +! [i,j,k+1]-index + xip1 = ll + bdim_i*bdim_j + IF (par_name(proza_lock(xip1))==1) kk = kk + 1 + ELSE + kk = kk + 1 + END IF +! can the block be computed ? + IF (kk==3) THEN +! now: [xi,yi,zi] is the current computable block 'll', private 'jj' + GO TO 201 + END IF + END IF + END DO +! polling ... needs to found a free block + GO TO 200 +! found a computable block +201 CONTINUE + +! compute begin & end + i_e = min(block_i,n_i-((xi-1)*block_i)) + j_e = min(block_j,n_j-((yi-1)*block_j)) + k_e = min(block_k,n_k-((zi-1)*block_k)) +! block index dim-1 + xim1 = max(xi-1,1) + yim1 = max(yi-1,1) + zim1 = max(zi-1,1) + +! solve [U]x[t]=[b] + CALL flu_right2(block_i,block_j,block_k,i_e,j_e,k_e, & + xloc(1,jj),lud(1,jj),lme(1,jj),lmf(1,jj),lmg(1,jj), & + bound_block(1,xim1,yi,zi),bound_block(isurf,xi,yim1,zi), & + bound_block(ijsurf,xi,yi,zim1),bound_block(1,xi,yi,zi), & + bound_block(isurf,xi,yi,zi),bound_block(ijsurf,xi,yi,zi), & + xim1-xi+1,yim1-yi+1,zim1-zi+1) + + CALL par_disab(proza_lock(ll)) + + IF ((xi==1) .AND. (yi==1) .AND. (zi==1)) THEN + CALL par_reset(proza_lock) + CALL set_dval(ijksurf,0.D0,bound_block(1,xi,yi,zi)) + END IF + + END DO + +! ----------------------------------------------------------------- + + RETURN + END + +!> @brief compute [L]-part by solving [L] x [t] = [b] +!> @param[in] bloc vector [b] +!> @param[in,out] xloc result vector [t] +!> @param[in] UA thread local blocks of the 1. diagonal of [L] +!> @param[in] UB thread local blocks of the 2. diagonal of [L] +!> @param[in] UC thread local blocks of the 3. diagonal of [L] +!> @param[in] UD thread local blocks of the helper diagonal [UD] of [L] +!> @param[in] ldI leading dimensions in I direction +!> @param[in] ldJ leading dimensions in J direction +!> @param[in] ldK leading dimensions in K direction +!> @param[in] i_e block size in I direction +!> @param[in] j_e block size in J direction +!> @param[in] k_e block size in K direction +!> @param[in] xloc_im1 global boundary buffer from the -1 neighbour in I direction +!> @param[in] xloc_jm1 global boundary buffer from the -1 neighbour in J direction +!> @param[in] xloc_km1 global boundary buffer from the -1 neighbour in K direction +!> @param[out] xloc_ip1 global boundary buffer to the +1 neighbour in I direction +!> @param[out] xloc_jp1 global boundary buffer to the +1 neighbour in J direction +!> @param[out] xloc_kp1 global boundary buffer to the +1 neighbour in K direction +!> @param[in] UD_im1 local UD-buffer from the -1 neighbour in I direction +!> @param[in] UD_jm1 local UD-buffer from the -1 neighbour in J direction +!> @param[in] UD_km1 local UD-buffer from the -1 neighbour in K direction +!> @param[in] ci 0: copy boundary values in [xloc_ip1], <>0: do nothing +!> @param[in] cj 0: copy boundary values in [xloc_jp1], <>0: do nothing +!> @param[in] ck 0: copy boundary values in [xloc_kp1], <>0: do nothing + SUBROUTINE flu_left2(ldi,ldj,ldk,i_e,j_e,k_e,bloc,xloc,ua,ub,uc, & + ud,xloc_im1,xloc_jm1,xloc_km1,xloc_ip1,xloc_jp1,xloc_kp1, & + ud_im1,ud_jm1,ud_km1,ci,cj,ck) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vectors r,z + INTEGER i_e, j_e, k_e, i, j, k, ldi, ldj, ldk, ci, cj, ck +! vectors [r], [z] + DOUBLE PRECISION bloc(ldi,ldj,ldk), xloc(ldi,ldj,ldk) + DOUBLE PRECISION ua(ldi,ldj,ldk), ub(ldi,ldj,ldk) + DOUBLE PRECISION uc(ldi,ldj,ldk), ud(ldi,ldj,ldk) + +! use mod_blocking_size +! global boundary buffer + DOUBLE PRECISION xloc_im1(block_j,block_k) + DOUBLE PRECISION xloc_jm1(block_i,block_k) + DOUBLE PRECISION xloc_km1(block_i,block_j) + DOUBLE PRECISION xloc_ip1(block_j,block_k) + DOUBLE PRECISION xloc_jp1(block_i,block_k) + DOUBLE PRECISION xloc_kp1(block_i,block_j) +! local UD-buffer (-1) + DOUBLE PRECISION ud_im1(block_j,block_k) + DOUBLE PRECISION ud_jm1(block_i,block_k) + DOUBLE PRECISION ud_km1(block_i,block_j) + +!$OMP flush(xloc_im1, xloc_jm1, xloc_km1) + +! solve [L]x[t]=[b] +! [0D] + xloc(1,1,1) = bloc(1,1,1) - uc(1,1,1)*ud_im1(1,1)*xloc_im1(1,1 & + ) - ub(1,1,1)*ud_jm1(1,1)*xloc_jm1(1,1) - & + ua(1,1,1)*ud_km1(1,1)*xloc_km1(1,1) + + +! [1D-I] + DO i = 2, i_e + xloc(i,1,1) = bloc(i,1,1) - uc(i,1,1)*ud(i-1,1,1)*xloc(i-1,1 & + ,1) - ub(i,1,1)*ud_jm1(i,1)*xloc_jm1(i,1) - & + ua(i,1,1)*ud_km1(i,1)*xloc_km1(i,1) + END DO + +! [1D-J] + DO j = 2, j_e + xloc(1,j,1) = bloc(1,j,1) - uc(1,j,1)*ud_im1(j,1)*xloc_im1(j & + ,1) - ub(1,j,1)*ud(1,j-1,1)*xloc(1,j-1,1) - & + ua(1,j,1)*ud_km1(1,j)*xloc_km1(1,j) + END DO + +! [1D-K] + DO k = 2, k_e + xloc(1,1,k) = bloc(1,1,k) - uc(1,1,k)*ud_im1(1,k)*xloc_im1(1 & + ,k) - ub(1,1,k)*ud_jm1(1,k)*xloc_jm1(1,k) - & + ua(1,1,k)*ud(1,1,k-1)*xloc(1,1,k-1) + END DO + + +! [2D-I] + DO k = 2, k_e + DO j = 2, j_e + xloc(1,j,k) = bloc(1,j,k) - uc(1,j,k)*ud_im1(j,k)*xloc_im1 & + (j,k) - ub(1,j,k)*ud(1,j-1,k)*xloc(1,j-1,k) - & + ua(1,j,k)*ud(1,j,k-1)*xloc(1,j,k-1) + END DO + END DO + +! [2D-J] + DO k = 2, k_e + DO i = 2, i_e + xloc(i,1,k) = bloc(i,1,k) - uc(i,1,k)*ud(i-1,1,k)*xloc(i-1 & + ,1,k) - ub(i,1,k)*ud_jm1(i,k)*xloc_jm1(i,k) - & + ua(i,1,k)*ud(i,1,k-1)*xloc(i,1,k-1) + END DO + END DO + +! [2D-K] + DO j = 2, j_e + DO i = 2, i_e + xloc(i,j,1) = bloc(i,j,1) - uc(i,j,1)*ud(i-1,j,1)*xloc(i-1 & + ,j,1) - ub(i,j,1)*ud(i,j-1,1)*xloc(i,j-1,1) - & + ua(i,j,1)*ud_km1(i,j)*xloc_km1(i,j) + END DO + END DO + + +! [3D] + DO k = 2, k_e + DO j = 2, j_e + DO i = 2, i_e + xloc(i,j,k) = bloc(i,j,k) - uc(i,j,k)*ud(i-1,j,k)*xloc(i & + -1,j,k) - ub(i,j,k)*ud(i,j-1,k)*xloc(i,j-1,k) - & + ua(i,j,k)*ud(i,j,k-1)*xloc(i,j,k-1) + END DO + END DO + END DO + + +! boundary exchange +! [2D-I] + IF (ci==0) THEN + DO k = 1, k_e + DO j = 1, j_e + xloc_ip1(j,k) = xloc(i_e,j,k) + END DO + END DO + END IF + +! [2D-J] + IF (cj==0) THEN + DO k = 1, k_e + DO i = 1, i_e + xloc_jp1(i,k) = xloc(i,j_e,k) + END DO + END DO + END IF + +! [2D-K] + IF (ck==0) THEN + DO j = 1, j_e + DO i = 1, i_e + xloc_kp1(i,j) = xloc(i,j,k_e) + END DO + END DO + END IF + +!$OMP flush(xloc_ip1, xloc_jp1, xloc_kp1) + + RETURN + END + +!> @brief compute [U]-part by solving [U] x [x] = [t] +!> @param[in] ldI leading dimensions in I direction +!> @param[in] ldJ leading dimensions in J direction +!> @param[in] ldK leading dimensions in K direction +!> @param[in] i_e block size in I direction +!> @param[in] j_e block size in J direction +!> @param[in] k_e block size in K direction +!> @param[in,out] xloc result vector [x], [t] as input +!> @param[in] UD thread local blocks of the helper diagonal [UD] of [U] +!> @param[in] UE thread local blocks of the 2. diagonal of [U] +!> @param[in] UF thread local blocks of the 3. diagonal of [U] +!> @param[in] UG thread local blocks of the 4. diagonal of [U] +!> @param[out] xloc_im1 global boundary buffer to the -1 neighbour in I direction +!> @param[out] xloc_jm1 global boundary buffer to the -1 neighbour in J direction +!> @param[out] xloc_km1 global boundary buffer to the -1 neighbour in K direction +!> @param[in] xloc_ip1 global boundary buffer from the +1 neighbour in I direction +!> @param[in] xloc_jp1 global boundary buffer from the +1 neighbour in J direction +!> @param[in] xloc_kp1 global boundary buffer from the +1 neighbour in K direction +!> @param[in] ci 0: copy boundary values in [xloc_im1], <>0: do nothing +!> @param[in] cj 0: copy boundary values in [xloc_jm1], <>0: do nothing +!> @param[in] ck 0: copy boundary values in [xloc_km1], <>0: do nothing + SUBROUTINE flu_right2(ldi,ldj,ldk,i_e,j_e,k_e,xloc,ud,ue,uf,ug, & + xloc_im1,xloc_jm1,xloc_km1,xloc_ip1,xloc_jp1,xloc_kp1,ci,cj, & + ck) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vectors r,z + INTEGER k_e, j_e, i_e, i, j, k, ldi, ldj, ldk, ci, cj, ck + +! vectors [z] + DOUBLE PRECISION xloc(ldi,ldj,ldk) + DOUBLE PRECISION ud(ldi,ldj,ldk), ue(ldi,ldj,ldk) + DOUBLE PRECISION uf(ldi,ldj,ldk), ug(ldi,ldj,ldk) + +! use mod_blocking_size +! global boundary buffer + DOUBLE PRECISION xloc_im1(block_j,block_k) + DOUBLE PRECISION xloc_jm1(block_i,block_k) + DOUBLE PRECISION xloc_km1(block_i,block_j) + DOUBLE PRECISION xloc_ip1(block_j,block_k) + DOUBLE PRECISION xloc_jp1(block_i,block_k) + DOUBLE PRECISION xloc_kp1(block_i,block_j) + +!$OMP flush(xloc_ip1, xloc_jp1, xloc_kp1) + +! solve [U]x[x]=[t] +! [0D] + xloc(i_e,j_e,k_e) = (xloc(i_e,j_e,k_e)-ue(i_e,j_e,k_e)* & + xloc_ip1(j_e,k_e)-uf(i_e,j_e,k_e)*xloc_jp1(i_e,k_e)- & + ug(i_e,j_e,k_e)*xloc_kp1(i_e,j_e))*ud(i_e,j_e,k_e) + + +! [1D-I] + DO i = i_e - 1, 1, -1 + xloc(i,j_e,k_e) = (xloc(i,j_e,k_e)-ue(i,j_e,k_e)*xloc(i+1, & + j_e,k_e)-uf(i,j_e,k_e)*xloc_jp1(i,k_e)- & + ug(i,j_e,k_e)*xloc_kp1(i,j_e))*ud(i,j_e,k_e) + END DO + +! [1D-J] + DO j = j_e - 1, 1, -1 + xloc(i_e,j,k_e) = (xloc(i_e,j,k_e)-ue(i_e,j,k_e)*xloc_ip1(j, & + k_e)-uf(i_e,j,k_e)*xloc(i_e,j+1,k_e)- & + ug(i_e,j,k_e)*xloc_kp1(i_e,j))*ud(i_e,j,k_e) + END DO + +! [1D-K] + DO k = k_e - 1, 1, -1 + xloc(i_e,j_e,k) = (xloc(i_e,j_e,k)-ue(i_e,j_e,k)*xloc_ip1( & + j_e,k)-uf(i_e,j_e,k)*xloc_jp1(i_e,k)- & + ug(i_e,j_e,k)*xloc(i_e,j_e,k+1))*ud(i_e,j_e,k) + END DO + + +! [2D-I] + DO k = k_e - 1, 1, -1 + DO j = j_e - 1, 1, -1 + xloc(i_e,j,k) = (xloc(i_e,j,k)-ue(i_e,j,k)*xloc_ip1(j,k)- & + uf(i_e,j,k)*xloc(i_e,j+1,k)-ug(i_e,j,k)*xloc(i_e,j,k+1)) & + *ud(i_e,j,k) + END DO + END DO + +! [2D-J] + DO k = k_e - 1, 1, -1 + DO i = i_e - 1, 1, -1 + xloc(i,j_e,k) = (xloc(i,j_e,k)-ue(i,j_e,k)*xloc(i+1,j_e,k) & + -uf(i,j_e,k)*xloc_jp1(i,k)-ug(i,j_e,k)*xloc(i,j_e,k+1))* & + ud(i,j_e,k) + END DO + END DO + +! [2D-K] + DO j = j_e - 1, 1, -1 + DO i = i_e - 1, 1, -1 + xloc(i,j,k_e) = (xloc(i,j,k_e)-ue(i,j,k_e)*xloc(i+1,j,k_e) & + -uf(i,j,k_e)*xloc(i,j+1,k_e)-ug(i,j,k_e)*xloc_kp1(i,j))* & + ud(i,j,k_e) + END DO + END DO + + +! [3D] + DO k = k_e - 1, 1, -1 + DO j = j_e - 1, 1, -1 + DO i = i_e - 1, 1, -1 + xloc(i,j,k) = (xloc(i,j,k)-ue(i,j,k)*xloc(i+1,j,k)-uf(i, & + j,k)*xloc(i,j+1,k)-ug(i,j,k)*xloc(i,j,k+1))*ud(i,j,k) + END DO + END DO + END DO + + +! boundary exchange +! [2D-I] + IF (ci==0) THEN + DO k = 1, k_e + DO j = 1, j_e + xloc_im1(j,k) = xloc(1,j,k) + END DO + END DO + END IF + +! [2D-J] + IF (cj==0) THEN + DO k = 1, k_e + DO i = 1, i_e + xloc_jm1(i,k) = xloc(i,1,k) + END DO + END DO + END IF + +! [2D-K] + IF (ck==0) THEN + DO j = 1, j_e + DO i = 1, i_e + xloc_km1(i,j) = xloc(i,j,1) + END DO + END DO + END IF + +!$OMP flush(xloc_im1, xloc_jm1, xloc_km1) + + RETURN + END + +!> @brief compute a processor grid distribution +!> @param[in] lbl_size cache (block) size +!> @param[in] P number of threads +!> @param[out] bi block size in each dimension +!> @param[out] bj block size in each dimension +!> @param[out] bk block size in each dimension +!> @param[in] ni grid dimension in I0 direction +!> @param[in] nj grid dimension in I0 direction +!> @param[in] nk grid dimension in I0 direction + SUBROUTINE proz_grid(lbl_size,p,bi,bj,bk,ni,nj,nk) + use mod_genrl + use mod_linfos + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k, l, m + INTEGER bi, bj, bk, p, ii, jj, kk,ni,nj,nk + INTEGER qwurz, lbl_size + INTRINSIC sqrt, max, dble, int + INTEGER vec_anz, ct_cm +! vec_anz : [A B C + D + W + X] =#6 + PARAMETER (vec_anz=6) + PARAMETER (ct_cm=55) + INTEGER cache2d_size +! 8192 Double-Precisions (64KByte) + PARAMETER (cache2d_size = 8192) + DOUBLE PRECISION dii, djj, dkk, dti, dtj, dtk +! ! manuell block size for benchmarking ! + IF (linfos(4)==-1000) THEN + bi = block_i + bj = block_j + bk = block_k + RETURN + END IF +! --------- NEW METHOD +! compute block size for big models + IF (ni*nj*nk>=4*cache2d_size) THEN +! - preset: I0 dimension + dii = -1.0d0 + bi = -1 + DO ii = min(ni,20), min(ni,70) + i = (ni-1) /ii + i = ni -i*ii + dti = dble(i)/dble(ii) + IF (dti>=dii) THEN + dii = dti -1.0D-10 + bi = ii + END IF + END DO +! - preset: J0 dimension + djj = -1.0d0 + bj = -1 + DO jj = min(nj,20), min(nj,40) + j = (nj-1) /jj + j = nj -j*jj + dtj = dble(j)/dble(jj) + IF (dtj>=djj) THEN + djj = dtj -1.0D-10 + bj = jj + END IF + END DO +! - preset: K0 dimension + dkk = -1.0d0 + bk = -1 + DO kk = nk, min(nk,4), -1 + k = (nk-1) /kk + k = nk -k*kk + dtk = dble(k)/dble(kk) + IF (dtk>=dkk) THEN + dkk = dtk -1.0D-10 + bk = kk + END IF + END DO +! search in the I0,J0,K0 combination for a 64K-cache-fit + l = ni*nj*nk + DO kk = nk, min(nk,4), -1 + k = (nk-1) /kk + k = nk -k*kk + dtk = dble(k)/dble(kk) + IF (dtk>=dkk) THEN + DO jj = min(nj,20), min(nj,40) + j = (nj-1) /jj + j = nj -j*jj + dtj = dble(j)/dble(jj) + IF (dtj>=djj) THEN + DO ii = min(ni,20), min(ni,70) + i = (ni-1) /ii + i = ni -i*ii + dti = dble(i)/dble(ii) + IF (dti>=dii) THEN +! proof block size [m] close to cache block size [cache2d_size] + m = abs(ii*jj*kk -cache2d_size) + IF (m<=l) THEN + dii = dti -1.0D-10 + bi = ii + djj = dtj -1.0D-10 + bj = jj + dkk = dtk -1.0D-10 + bk = kk + l = m + END IF + END IF + END DO + END IF + END DO + END IF + END DO + ELSE +! --------- OLD METHOD +! ! automatic block size computation ! +! minimal block length in I0 direction + IF (ni>ct_cm) THEN +! 2D or 3D partitioning +! a little bit more is better +! 0.0-1.99: 1; 2.0-2.99: 2; ... + bi = max(ni/ct_cm,1) + bi = (ni-1)/bi + 1 +! number of blocks in J0*K0 +! ik_bl = bi*J0*K0*veC_anz/lbl_size +! size of J0*K0 blocks matching the cache size +! J0*K0/ik_bl +! ideal size for J0 and K0 +! qwurz = int(sqrt(dble(J0*K0/ik_bl))) + qwurz = max(int(sqrt(dble(lbl_size/(bi*vec_anz)))),1) +! J0 dimension +! a little bit more is better +! 0.0-1.99: 1; 2.0-2.99: 2; ... + bj = (nj-1)/qwurz + 1 + bj = (nj-1)/bj + 1 +! rest for K0 dimension +! a little bit more is better +! 0.0-1.99: 1; 2.0-2.99: 2; ... + bk = vec_anz*(nk-1)*bj*bi/lbl_size + 1 + bk = (nk-1)/bk + 1 + ELSE IF (ni*nj>ct_cm) THEN +! simple 2D partitioning, when enough elements +! I0 dimension + bi = ni +! number of cache blocks in J0*K0 +! (J0 *K0 *vec_anz *bi) /lbl_size +! ideal size for J0 and K0 + qwurz = max(int(sqrt(dble((nj*nk*vec_anz*bi)/lbl_size))),1) +! J0 dimension +! a little bit more is better +! 0.0-1.99: 1; 2.0-2.99: 2; ... + bj = max(ni*nj/ct_cm,1) + bj = (nj-1)/bj + 1 + bj = max(bj,(nj-1)/qwurz+1) +! rest for K0 dimension +! a little bit more is better +! 0.0-1.99: 1; 2.0-2.99: 2; ... + bk = vec_anz*(nk-1)*bj*bi/lbl_size + 1 + bk = (nk-1)/bk + 1 + ELSE +! ! in case of a 2D model and a too small I0, no parallelization ! + bi = ni + bj = nj + bk = nk + END IF + END IF +! --------- + RETURN + END + +!> @param[in] ni grid dimension in I0 direction +!> @param[in] nj grid dimension in J0 direction +!> @param[in] nk grid dimension in K0 direction +!> @brief initialise [proza]-thread association for parallel computation + SUBROUTINE par_init2(ni,nj,nk) + use arrays + use mod_genrl + use mod_linfos + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k + INCLUDE 'OMP_TOOLS.inc' + INTEGER bi, bj, bk, p, pa, ni,nj,nk + INTEGER li, lj, lk, maxlevel + INTEGER, ALLOCATABLE :: speed(:) + INTEGER, ALLOCATABLE :: nbl_proz(:), sbl_proz(:), lev_idx(:,:) + INTEGER ilev_b, ilev_e, pro_b, pro_e, t_max + INTEGER subbl, parmax, parlen + PARAMETER (subbl=16) + DOUBLE PRECISION speedup, speedup_vec +! use mod_blocking_size + INTRINSIC max, min, log10, dble, int +#ifdef BENCH + character (len=40) :: bench_format +#endif + +! number of processors + p = tlevel_1 + +! minimal block length for each dimension + i = subbl + 1 +123 i = i - 1 + CALL proz_grid(i*bl_size/subbl,p,bi,bj,bk,ni,nj,nk) + li = (ni-1)/bi + 1 + lj = (nj-1)/bj + 1 + lk = (nk-1)/bk + 1 +! max. useable threads + parmax = max(max(min(li,lj),min(li,lk)),min(lj,lk)) +! # of max. thread runs + parlen = max(max(li,lj),lk) - min(parmax,p) +!debug write(*,*) '[parmax,parlen,i]:',parmax,parlen,i + IF ((parmax<p .OR. parlen<p) .AND. i>1) GO TO 123 + + block_i = bi + block_j = bj + block_k = bk + bdim_i = li + bdim_j = lj + bdim_k = lk + + ALLOCATE(proza(li,lj,lk)) + +! compute levels, all blocks for the same level are independent + maxlevel = 0 + DO k = 1, lk + DO j = 1, lj + DO i = 1, li + proza(i,j,k) = 0 +! set to maximum of all previous neighboars + IF (i>1) proza(i,j,k) = max(proza(i,j,k),proza(i-1,j,k)) + IF (j>1) proza(i,j,k) = max(proza(i,j,k),proza(i,j-1,k)) + IF (k>1) proza(i,j,k) = max(proza(i,j,k),proza(i,j,k-1)) +! increase level + proza(i,j,k) = proza(i,j,k) + 1 + maxlevel = max(maxlevel,proza(i,j,k)) + END DO + END DO + END DO + + ALLOCATE(speed(maxlevel)) + DO i = 1, maxlevel + speed(i) = 0 + END DO +! estimate max number of threads per level + DO k = 1, lk + DO j = 1, lj + DO i = 1, li +! ProzA from 1..(P) + speed(proza(i,j,k)) = speed(proza(i,j,k)) + 1 + END DO + END DO + END DO +! PA: maximum number of independent threads over all levels +! speedup : approx. speedup + pa = 0 + speedup = 0.0D0 + DO i = 1, maxlevel + pa = max(speed(i),pa) + speedup = speedup + dble(speed(i))/dble(min(speed(i),p)) + END DO + speedup = dble(li*lj*lk)/speedup + + +! max number of blocks for each thread + ALLOCATE(nbl_proz(p)) +! used (setup) number of blocks for each thread during each level + ALLOCATE(sbl_proz(p)) +! index of blocks for this level + ALLOCATE(lev_idx(3,pa)) + +! number of blocks equal for each thread + i = (li*lj*lk)/p + DO j = 1, p + nbl_proz(j) = i + END DO +! overhead of blocks distributed over all threads + i = li*lj*lk - i*p + DO j = 1, i + nbl_proz(j) = nbl_proz(j) + 1 + END DO + speedup_vec = dble(li*lj*lk)/dble(nbl_proz(1)) +! max number of blocks (the first thread has the highest number) + max_blocks = nbl_proz(1) + +! for each level distribute the blocks of each thread (bi-directional) + ilev_b = 1 + ilev_e = maxlevel +1000 CONTINUE +! first: forward direction +! init + pro_b = 0 + t_max = 0 + DO i = 1, p + sbl_proz(i) = 0 + END DO +! search for the 'ilev_b' level + DO k = 1, lk + DO j = 1, lj + DO i = 1, li +! right [i,j,k]-index for this level + IF (proza(i,j,k)==ilev_b) THEN + t_max = t_max + 1 +! next thread with free blocks +1001 pro_b = mod(pro_b,p) + 1 +! skip this thread: +! 1. no blocks +! 2. already one block +! and not enough for later levels + IF (nbl_proz(pro_b)<=0 .OR. (sbl_proz(pro_b)>0 .AND. ( & + maxlevel-2*ilev_b+1)>=nbl_proz(pro_b))) GO TO 1001 +! mark the block for this level + nbl_proz(pro_b) = nbl_proz(pro_b) - 1 + sbl_proz(pro_b) = sbl_proz(pro_b) + 1 + lev_idx(1,t_max) = i + lev_idx(2,t_max) = j + lev_idx(3,t_max) = k + END IF + END DO + END DO + END DO +! distribute the blocks + pro_b = 1 + CALL distribute_bl(t_max,p,pro_b,sbl_proz,lev_idx) +! second: backward direction + IF (ilev_b==ilev_e) GO TO 1020 +! init + pro_e = 1 + t_max = 0 + DO i = 1, p + sbl_proz(i) = 0 + END DO +! search for the 'ilev_e' level + DO k = lk, 1, -1 + DO j = lj, 1, -1 + DO i = li, 1, -1 +! right [i,j,k]-index for this level + IF (proza(i,j,k)==ilev_e) THEN + t_max = t_max + 1 +! next thread with free blocks +1011 pro_e = mod(pro_e+p-2,p) + 1 +! skip this thread: +! 1. no blocks +! 2. already one block +! and not enough for later levels + IF (nbl_proz(pro_e)<=0 .OR. (sbl_proz(pro_e)>0 .AND. ( & + maxlevel-2*ilev_b)>=nbl_proz(pro_e))) GO TO 1011 +! mark the block for this level + nbl_proz(pro_e) = nbl_proz(pro_e) - 1 + sbl_proz(pro_e) = sbl_proz(pro_e) + 1 + lev_idx(1,t_max) = i + lev_idx(2,t_max) = j + lev_idx(3,t_max) = k + END IF + END DO + END DO + END DO +! distribute the blocks + pro_e = p + CALL distribute_bl(t_max,p,pro_e,sbl_proz,lev_idx) + +! next levels +1020 CONTINUE + ilev_b = ilev_b + 1 + ilev_e = ilev_e - 1 + IF (ilev_b<=ilev_e) GO TO 1000 + + + DEALLOCATE(lev_idx) + DEALLOCATE(sbl_proz) + DEALLOCATE(nbl_proz) + DEALLOCATE(speed) + +! setup return values + DO k = 1, lk + DO j = 1, lj + DO i = 1, li +! ProzA : [0..(PA-1)] + proza(i,j,k) = -proza(i,j,k) - 1 + END DO + END DO + END DO + +#ifdef BENCH + IF (p>1) THEN + WRITE(*,'(A)') ' [I] : ILU block - thread assignment:' + WRITE(bench_format,'(A,I2,A,I2,A,I2,A)') '(7X,', lk, '(', & + li, 'I', int(log10(dble(pa))) + 2, ',2X))' + DO j = 1, lj + WRITE(*,bench_format) ((proza(i,j,k),i=1,li),k=1,lk) + END DO + END IF +! 'speed' should now be the number of blocks for each thread +!aw write(*,'(A)') ' [I] : Number of bloCks for eaCh thread:' +!aw write (benCh_format,'(A,I2,A,I2,A)') '(A,',P,'I', +!aw & int(log10(dble(speed(1))))+2,',A)' +!aw write(*,benCh_format) ' [',(i-1,i=1,P),'] thread' +!aw write(*,benCh_format) ' [',(speed(i),i=1,P),'] bloCks' + WRITE(*,'(A,3(I5,A),3(I3,A))') ' [I] : ILU: block size =[', & + bi, ',', bj, ',', bk, '], dim=[', li, ',', lj, ',', lk, ']' + WRITE(*,'(A,F7.2)') & + ' theoretical speedup for solver only :', speedup_vec + WRITE(*,'(A,F7.2)') & + ' theoretical speedup for ILU only :', speedup + CALL write_grid() +#endif + IF (linfos(4)>=1) THEN + WRITE(*,'(A,F7.2)') & + ' [I] : approx. speedup for the full solver :', & + (2.0D0*speedup+1.0D0*speedup_vec)/3.0D0 + END IF + + RETURN + END + +!> @brief search for nearest neighbours and distributes the blocks, writes output in [proza] +!> @param[in] t_max number of blocks +!> @param[in] P number of threads (processor cores) +!> @param[in] pro_be initial thread index, switch with 1: forward counting, [P]: backward counting +!> @param[in,out] sbl_proz blocks per thread counter +!> @param[in] lev_idx i,j,k index for each block + SUBROUTINE distribute_bl(t_max,p,pro_be,sbl_proz,lev_idx) + use arrays + use mod_OMP_TOOLS + use mod_genrl + use mod_linfos + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k + INCLUDE 'OMP_TOOLS.inc' + INTEGER p, t_max, pro_be + INTEGER sbl_proz(p), lev_idx(3,t_max) + INTEGER tidx, ii, jj, kk, ll, mm + + tidx = pro_be + DO ii = 1, t_max +! thread for the next block +2001 IF (sbl_proz(tidx)<=0) THEN + IF (pro_be==p) THEN +! backward + tidx = mod(tidx+p-2,p) + 1 + ELSE +! forward + tidx = mod(tidx,p) + 1 + END IF + GO TO 2001 + END IF + sbl_proz(tidx) = sbl_proz(tidx) - 1 +! search the best fit (kk: most neighboars) + ll = -1 + mm = 1 + DO jj = 1, t_max + i = lev_idx(1,jj) + j = lev_idx(2,jj) + k = lev_idx(3,jj) + kk = 0 + IF (i>1) THEN + IF (proza(i-1,j,k)==-tidx) kk = kk + 1 + END IF + IF (j>1) THEN + IF (proza(i,j-1,k)==-tidx) kk = kk + 1 + END IF + IF (k>1) THEN + IF (proza(i,j,k-1)==-tidx) kk = kk + 1 + END IF + IF (i<bdim_i) THEN + IF (proza(i+1,j,k)==-tidx) kk = kk + 1 + END IF + IF (j<bdim_j) THEN + IF (proza(i,j+1,k)==-tidx) kk = kk + 1 + END IF + IF (k<bdim_k) THEN + IF (proza(i,j,k+1)==-tidx) kk = kk + 1 + END IF + IF (kk>ll .AND. proza(i,j,k)>=0) THEN +! better fit + ll = kk + mm = jj + END IF + END DO + proza(lev_idx(1,mm),lev_idx(2,mm),lev_idx(3,mm)) = -tidx +! old strait-forward distribution +!aw ProzA(lev_idx(1,i),lev_idx(2,i),lev_idx(3,i)) = -tidx + END DO + RETURN + END + +!> @brief function wrapper for array [proza] +!> @param[in] i cell index, direction I0 +!> @param[in] j cell index, direction J0 +!> @param[in] k cell index, direction K0 +!> @return value of [proza(i,j,k)] + INTEGER FUNCTION fkt_proza(i,j,k) + use arrays + IMPLICIT NONE + INTEGER i, j, k + + fkt_proza = proza(i,j,k) + + RETURN + END + +!> @brief writes ILU thread grid in tecplot-format +!> @details +!> writes ILU thread grid in tecplot-format\n +!> for each block an eight-node cube is created\n + SUBROUTINE write_grid() + use arrays + use mod_blocking_size + IMPLICIT NONE +! use mod_blocking_size + INTEGER i, j, k + + + OPEN(76,file='thread_grid.plt',status='unknown',blank='null') + + WRITE(76,'(1A)') 'variables = "i", "j", "k", "thread"' + WRITE(76,'(3(1A,I5),1A)') 'zone i=', bdim_i*2, ', j=', & + bdim_j*2, ', k=', bdim_k*2, ', f=point' + + DO k = 1, bdim_k + DO j = 1, bdim_j + DO i = 1, bdim_i + WRITE(76,'(3F6.2,1I6)') dble(i) - 0.99D0, & + dble(j) - 0.99D0, dble(k) - 0.99D0, proza(i,j,k) + WRITE(76,'(3F6.2,1I6)') dble(i), dble(j) - 0.99D0, & + dble(k) - 0.99D0, proza(i,j,k) + END DO + DO i = 1, bdim_i + WRITE(76,'(3F6.2,1I6)') dble(i) - 0.99D0, dble(j), & + dble(k) - 0.99D0, proza(i,j,k) + WRITE(76,'(3F6.2,1I6)') dble(i), dble(j), & + dble(k) - 0.99D0, proza(i,j,k) + END DO + END DO + DO j = 1, bdim_j + DO i = 1, bdim_i + WRITE(76,'(3F6.2,1I6)') dble(i) - 0.99D0, & + dble(j) - 0.99D0, dble(k), proza(i,j,k) + WRITE(76,'(3F6.2,1I6)') dble(i), dble(j) - 0.99D0, & + dble(k), proza(i,j,k) + END DO + DO i = 1, bdim_i + WRITE(76,'(3F6.2,1I6)') dble(i) - 0.99D0, dble(j), & + dble(k), proza(i,j,k) + WRITE(76,'(3F6.2,1I6)') dble(i), dble(j), dble(k), & + proza(i,j,k) + END DO + END DO + END DO + + CLOSE(76) + RETURN + END diff --git a/solve/omp_sym_solve.f90 b/solve/omp_sym_solve.f90 new file mode 100644 index 0000000..2c3286a --- /dev/null +++ b/solve/omp_sym_solve.f90 @@ -0,0 +1,180 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], CG algorithm based +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is s.p.d. Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_sym_solve(n_i,n_j,n_k,x,b,depsilon,mbc_mask, & + max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector x, r, z, s, b, p, q +! ld_N : leading dimension of [locTMP] + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tanz, tpos + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_cg.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_CG stuff +! work : control variable : what is to do out of this subroutine, +! see more discription in 'pre_cg.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1) & +!$OMP default(shared) & +!$OMP private(tanz,tpos,iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 6 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! preload ([M]x[x]) in [s] + CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,s),ma,mb,mc,md,me,mf,mg) +! implicit barrier here + +10 CONTINUE + + +! cg-routines without Pre-Cond. +! step : is the return-lable for pre_cg() + CALL pre_cg(tanz,x(tpos),b(tpos),n,loctmp(tpos,1),depsilon, & + dnrm(tpos),max_it,criteria,res0,work,ipar,rpar,lpar) +! implicit barrier here + + IF ((work==mvp) .OR. (work==mvpx)) THEN +! solve: [M]x[z]=[r] -> [z]:=[A^-1]x[r] +! here [M] can be a substituted Matrix [T] -> solve: [T]x[z]=[r] + CALL myprco(n,loctmp(1,r),loctmp(1,z)) +!$OMP barrier + +! [s]:=[M]x[z] + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,z),loctmp(1,s),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + END IF + +! [v]:=[M]x[x], for advanced precision + IF (work==mvpx) CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,v),ma,mb, & + mc,md,me,mf,mg) +! implicit barrier here + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 + +!$OMP end parallel + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_sym_solve_diag.f90 b/solve/omp_sym_solve_diag.f90 new file mode 100644 index 0000000..7d3992c --- /dev/null +++ b/solve/omp_sym_solve_diag.f90 @@ -0,0 +1,181 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], CG algorithm based with Diagonal preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is s.p.d. Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_sym_solve_diag(n_i,n_j,n_k,x,b,depsilon,mbc_mask, & + max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector x, r, z, s, b, p, q +! ld_N : leading dimension of [locTMP] + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tanz, tpos + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_cg.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_CG stuff +! work : control variable : what is to do out of this subroutine, +! see more discription in 'pre_cg.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1) & +!$OMP default(shared) & +!$OMP private(tanz,tpos,iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 6 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +! allocate(rpar(6 +4 *OMP_GET_NUM_of_THREADS())) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! preload ([M]x[x]) in [s] + CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,s),ma,mb,mc,md,me,mf,mg) +! implicit barrier here + +10 CONTINUE + + +! cg-routines without Pre-Cond. +! step : is the return-lable for pre_cg() + CALL pre_cg(tanz,x(tpos),b(tpos),n,loctmp(tpos,1),depsilon, & + dnrm(tpos),max_it,criteria,res0,work,ipar,rpar,lpar) +! implicit barrier here + + IF ((work==mvp) .OR. (work==mvpx)) THEN +! solve: [M]x[z]=[r] -> [z]:=[A^-1]x[r] +! here [M] can be a substituted Matrix [T] -> solve: [T]x[z]=[r] + CALL diagprco(n,md,loctmp(1,r),loctmp(1,z)) +!$OMP barrier + +! [s]:=[M]x[z] + CALL omp_mvp(n_i,n_j,n_k,loctmp(1,z),loctmp(1,s),ma,mb,mc, & + md,me,mf,mg) +! implicit barrier here + END IF + +! [v]:=[M]x[x], for advanced precision + IF (work==mvpx) CALL omp_mvp(n_i,n_j,n_k,x,loctmp(1,v),ma,mb, & + mc,md,me,mf,mg) +! implicit barrier here + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 + +!$OMP end parallel + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/omp_sym_solve_ilu.f90 b/solve/omp_sym_solve_ilu.f90 new file mode 100644 index 0000000..1ec96fa --- /dev/null +++ b/solve/omp_sym_solve_ilu.f90 @@ -0,0 +1,302 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], CG algorithm based with ILU preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[in] UD helper diagonal elements for preconditioning +!> @param[out] bound_block boundary exchange buffer for each block, between the threads +!> @param[out] dnrm normalisation vector, temporary use +!> @param[out] lMA temporary thread local elements of the 1. diagonal of [M] +!> @param[out] lMB temporary thread local elements of the 2. diagonal of [M] +!> @param[out] lMC temporary thread local elements of the 3. diagonal of [M] +!> @param[out] lMD temporary thread local elements of the 4. diagonal of [M] +!> @param[out] lME temporary thread local elements of the 5. diagonal of [M] +!> @param[out] lMF temporary thread local elements of the 6. diagonal of [M] +!> @param[out] lMG temporary thread local elements of the 7. diagonal of [M] +!> @param[out] lUD temporary thread local elements of the helper diagonal [UD] +!> @param[out] lx temporary thread local elements of the solution vector [x] +!> @param[out] lb temporary thread local elements of the right side [b] +!> @param[out] ldnrm temporary thread local elements of the normalisation vector +!> @param[out] llocTMP temporary thread local elements of the local temporary vectors +!> @param[out] ud_block block buffer for helper diagonal [UD] +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> [M] is s.p.d. Matrix, only used in 'omp_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_sym_solve_ilu(n_i,n_j,n_k,x,b,depsilon,mbc_mask, & + max_it,criteria,ma,mb,mc,md,me,mf,mg,ud,bound_block,dnrm, & + lma,lmb,lmc,lmd,lme,lmf,lmg,lud,lx,lb,ldnrm,lloctmp, & + ud_block,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N_I*N_J*N_K : length of all vector r,z,s,t,v,p,y,t_pc,s_pc + INTEGER n_i, n_j, n_k, max_it, ismpl + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION res0, ud(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k) + DOUBLE PRECISION mc(n_i*n_j*n_k), md(n_i*n_j*n_k) + DOUBLE PRECISION me(n_i*n_j*n_k), mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + CHARACTER mbc_mask(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_cg.inc' +! use mod_blocking_size +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + +! global buffer for boundary exchange + DOUBLE PRECISION bound_block(block_i*block_j+block_i*block_k+ & + block_j*block_k,bdim_i,bdim_j,bdim_k,2) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) +! private copy for preconditioning + DOUBLE PRECISION lma(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lmb(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lmc(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lmd(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lme(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lmf(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lmg(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lud(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lx(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lb(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION ldnrm(max_blocks*block_i*block_j*block_k, & + tlevel_1) + DOUBLE PRECISION lloctmp(max_blocks*block_i*block_j*block_k, & + max_loctmp,tlevel_1) + DOUBLE PRECISION ud_block(block_i*block_j+block_i*block_k+ & + block_j*block_k,max_blocks,tlevel_1) + +! x,y,z-grid index for each block position + INTEGER, ALLOCATABLE :: xyz_block(:,:) + INTEGER lxyz_block, tid + +! Pre_CG stuff +! work : control variable : what is to do out of this subroutine, +! see more discription in 'pre_cg.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER xi, yi, zi, loc_mem, loc_memm1 + INTEGER criteria, i, j, k, fkt_proza + EXTERNAL fkt_proza +! openmp-private variables + INTEGER tpos, tanz +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + INTEGER, ALLOCATABLE :: proza_lock(:,:,:) + LOGICAL lpar(1) + + +! start values + work = start + res0 = 1.D+99 + + ALLOCATE(proza_lock(bdim_i,bdim_j,bdim_k)) + +!$OMP parallel & +!$OMP num_threads(Tlevel_1)& +!$OMP default(none) shared(Tlevel_1, ismpl)& +!$OMP shared(block_i,block_j,block_k, bdim_i,bdim_j,bdim_k,ipar,rpar)& +!$OMP shared(N_I,N_J,N_K, depsilon, max_It, criteria, res0, work,lpar)& +!$OMP shared(bound_block, MA,MB,MC,MD,ME,MF,MG,UD, x,b,ProzA_lock)& +!$OMP shared(mbc_mask, dnrm, ud_block, ldnrm, max_blocks)& +!$OMP shared(lMA,lMB,lMC,lMD,lUD,lME,lMF,lMG,lx,lb,llocTMP)& +!$OMP private(i,j,k, tid, loc_mem,loc_memm1, lxyz_block, xyz_block)& +!$OMP private(xi,yi,zi, iii, tpos, tanz) +!$ call omp_binding(ismpl) + + CALL omp_part(n_i*n_j*n_k,tpos,tanz) + tid = omp_get_his_thread_num() + 1 + +!$OMP master + iii = 6 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +! allocate(rpar(6 +4 *OMP_GET_NUM_of_THREADS())) + CALL par_reset(proza_lock) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier +! init ILU(0)-preconditioner, other start values + CALL prepare_ilu(n_i,n_j,n_k,ma,mb,mc,md,me,mf,mg,ud) + +! max number of private blocks = bdim_i*bdim_j*bdim_k + ALLOCATE(xyz_block(3,bdim_i*bdim_j*bdim_k)) + + lxyz_block = 0 + DO k = 1, bdim_k + DO j = 1, bdim_j + DO i = 1, bdim_i + IF (fkt_proza(i,j,k)==tid-1) THEN +! compute number of private blocks + lxyz_block = lxyz_block + 1 +! setup index information for each private block + xyz_block(1,lxyz_block) = i + xyz_block(2,lxyz_block) = j + xyz_block(3,lxyz_block) = k + END IF + END DO + END DO + END DO +! memory requirements + loc_mem = lxyz_block*block_i*block_j*block_k + loc_memm1 = max_blocks*block_i*block_j*block_k + +! make private copies from the global arrays +!$OMP barrier + CALL lcopy_ilu(n_i,n_j,n_k,ma,lma(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mb,lmb(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mc,lmc(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,md,lmd(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,ud,lud(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,me,lme(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mf,lmf(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,mg,lmg(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,x,lx(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,b,lb(1,tid),lxyz_block,xyz_block) + CALL lcopy_ilu(n_i,n_j,n_k,dnrm,ldnrm(1,tid),lxyz_block,xyz_block) +! lcopy_ilu of [locTMP] not needed, but of the cleanup +!aw-test Call set_dval(loC_memm1*max_loCTMP,0.d0,lloCTMP(1,1,tid)) + +! copy private [UD] surface (position-1) + DO i = 1, lxyz_block + CALL lsurf_ilu(n_i,n_j,n_k,i,ud,ud_block(1,i,tid),lxyz_block,xyz_block) + END DO + + +! INIT +! preload ([M]x[x]) in [z] + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lx(1,tid), & + lloctmp(1,s,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + +!************************************************************** + +10 CONTINUE + +! cg-routines without Pre-Cond. +! step : is the return-lable for pre_cg() + CALL pre_cg(loc_mem,lx(1,tid),lb(1,tid),loc_memm1, & + lloctmp(1,1,tid),depsilon,ldnrm(1,tid),max_it,criteria,res0, & + work,ipar,rpar,lpar) +! implicit barrier here + + IF ((work==mvp) .OR. (work==mvpx)) THEN +! solve: [M]x[z]=[r] -> [z]:=[A^-1]x[r] +! here [M] can be a substituted Matrix [T] -> solve: [T]x[z]=[r] + CALL omp_lu_solve2(n_i,n_j,n_k,lxyz_block,lloctmp(1,r,tid), & + lloctmp(1,z,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lud(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid), & + ud_block(1,1,tid),bound_block,xyz_block,proza_lock) +! need barrier here, [LU] and [MVP] modify "bound_block" +!$OMP barrier +! [s]:=[M]x[z] + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lloctmp(1,z,tid), & + lloctmp(1,s,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + END IF + +! [v]:=[M]x[x], for advanced precision + IF (work==mvpx) THEN +! need barrier here, both [MVP] modify "bound_block" +!$OMP barrier + CALL omp_mvp2(n_i,n_j,n_k,lxyz_block,lx(1,tid), & + lloctmp(1,v,tid),lma(1,tid),lmb(1,tid),lmc(1,tid), & + lmd(1,tid),lme(1,tid),lmf(1,tid),lmg(1,tid),bound_block, & + xyz_block) + END IF + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 +! at "work=ABORT", we can startup with a new [r^] + +!************************************************************** + + +! get the global [x] from private + CALL lcopy_bak_ilu(n_i,n_j,n_k,x,lx(1,tid),lxyz_block,xyz_block) + + DEALLOCATE(xyz_block) + +!$OMP end parallel + DEALLOCATE(rpar) + DEALLOCATE(proza_lock) + + RETURN + END diff --git a/solve/omp_sym_solve_ssor.f90 b/solve/omp_sym_solve_ssor.f90 new file mode 100644 index 0000000..d75e76b --- /dev/null +++ b/solve/omp_sym_solve_ssor.f90 @@ -0,0 +1,196 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief solve of : [M] x [x] = [b], CG algorithm based with SSOR preconditioning +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in,out] x solution vector [x], on start = start vector +!> @param[in] b right side, vector [b] +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] mbc_mask boundary condition pattern (mask) +!> @param[in] max_It max iteration number +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @param[out] locTMP local temporary vectors +!> @param[out] dnrm normalisation vector, temporary use +!> @param[in] ismpl local sample index +!> @details +!> solve of : [M] x [x] = [b]\n +!> but here compute : [M^] x [x^] = [b^]\n +!> [M] is s.p.d. Matrix, only used in 'ssor_MVP'\n +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread).\n + SUBROUTINE omp_sym_solve_ssor(n_i,n_j,n_k,x,b,depsilon,mbc_mask, & + max_it,criteria,ma,mb,mc,md,me,mf,mg,loctmp,dnrm,ismpl) + use mod_OMP_TOOLS + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : length of all vector x, r, z, s, b, p, q +! ld_N : leading dimension of [locTMP] + INTEGER n, n_i, n_j, n_k, max_it, ismpl + +! thread stuff + INTEGER tanz, tpos + +! vector x and b for [M]x[x]=[b] +! res0 ^= ||res0||, start residuel, given for 'criteria=0' + DOUBLE PRECISION x(n_i*n_j*n_k), b(n_i*n_j*n_k) + DOUBLE PRECISION res0 + CHARACTER mbc_mask(n_i*n_j*n_k) + DOUBLE PRECISION ma(n_i*n_j*n_k), mb(n_i*n_j*n_k), & + mc(n_i*n_j*n_k) + DOUBLE PRECISION md(n_i*n_j*n_k), me(n_i*n_j*n_k), & + mf(n_i*n_j*n_k) + DOUBLE PRECISION mg(n_i*n_j*n_k) + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_cg.inc' +! locTMP : space for local vectors, using to exchange data with +! 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R), +! for definitions see more in 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(n_i*n_j*n_k,max_loctmp) + DOUBLE PRECISION dnrm(n_i*n_j*n_k) + +! Pre_CG stuff +! work : control variable : what is to do out of this subroutine, +! see more discription in 'pre_cg.inc', +! on startup should set to 'work=START' + INTEGER work + +! break with enough precision + DOUBLE PRECISION depsilon + + INTEGER criteria +! openmp-shared variables + INTEGER ipar(5), iii + DOUBLE PRECISION, ALLOCATABLE :: rpar(:) + LOGICAL lpar(1) + + +! full number of elements + n = n_i*n_j*n_k + res0 = 1.D+99 + + +!************************************************************** + +! start values + work = start + +!$OMP parallel & +!$OMP num_threads(Tlevel_1) & +!$OMP default(shared) & +!$OMP private(tanz,tpos,iii) +!$ call omp_binding(ismpl) + + CALL omp_part(n,tpos,tanz) + +!$OMP master + iii = 6 + 4*omp_get_num_of_threads() + ALLOCATE(rpar(iii)) + CALL set_dval(iii,0.D0,rpar) +! allocate(rpar(6 +4 *OMP_GET_NUM_of_THREADS())) +!$OMP end master +! normalise the linear system, use [dnrm] to normalise the system + CALL norm_linsys(tanz,mbc_mask(tpos),b(tpos),x(tpos),ma(tpos), & + mb(tpos),mc(tpos),md(tpos),me(tpos),mf(tpos),mg(tpos), & + dnrm(tpos)) +!$OMP barrier + +! ###################### not parallel Code !!! ######################### +! prepare [b^] +! [b^] = D*(D+L)^(-1) * [b] + CALL ddl(n_i,n_j,n_k,b,loctmp(1,b_hat),ma,mb,mc,md) +! ################### above not parallel Code !!! ###################### + +! preload ([M]x[x]) in [s] + CALL ssor_mvp_single(n_i,n_j,n_k,x,loctmp(1,s),loctmp(1,mt), & + ma,mb,mc,md,me,mf,mg) +! impliciete barrier here + +10 CONTINUE + + +! cg-routines without Pre-Cond. +! step : is the return-lable for pre_cg() + CALL pre_cg(tanz,x(tpos),loctmp(tpos,b_hat),n,loctmp(tpos,1), & + depsilon,dnrm(tpos),max_it,criteria,res0,work,ipar,rpar, & + lpar) +! implicit barrier here + + IF ((work==mvp) .OR. (work==mvpx)) THEN +! solve: [M]x[z]=[r] -> [z]:=[A^-1]x[r] +! here [M] can be a substituted Matrix [T] -> solve: [T]x[z]=[r] + CALL myprco(n,loctmp(1,r),loctmp(1,z)) +!$OMP barrier + +! [s]:=[M]x[z] + CALL ssor_mvp_single(n_i,n_j,n_k,loctmp(1,z),loctmp(1,s), & + loctmp(1,mt),ma,mb,mc,md,me,mf,mg) +! implicit barrier here + END IF + +! [v]:=[M]x[x], for advanced precision + IF (work==mvpx) CALL ssor_mvp_single(n_i,n_j,n_k,x, & + loctmp(1,v),loctmp(1,mt),ma,mb,mc,md,me,mf,mg) +! implicit barrier here + + +! precision not enough ? + IF ((work/=fine) .AND. (work/=abort)) GO TO 10 + +!$OMP end parallel + +! ###################### not parallel Code !!! ######################### +! compute [x] +! [x] = (D+U)^(-1) * [x^] + CALL du(n_i,n_j,n_k,x,x,md,me,mf,mg) +! ################### above not parallel Code !!! ###################### + + DEALLOCATE(rpar) + +!************************************************************** + + + RETURN + END diff --git a/solve/p_pos_anz.f90 b/solve/p_pos_anz.f90 new file mode 100644 index 0000000..e99f734 --- /dev/null +++ b/solve/p_pos_anz.f90 @@ -0,0 +1,101 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief gives start position for proc. 'my_rank' +!> @param[in] N number of elements +!> @param[in] my_rank my rank to part the vector (lengths given by N) +!> @param[in] omp_P maximum rank to part the vector +!> @return start position of elements for this rank + INTEGER FUNCTION ppos(n,my_rank,omp_p) + IMPLICIT NONE + + INTEGER n +! OMP stuff + INTEGER my_rank, rank, omp_p +! tmp variables + INTEGER delta, schwelle, iall + +! checking border + rank = my_rank + IF (rank>(omp_p-1)) rank = omp_p - 1 + IF (rank<0) rank = 0 + + delta = n/omp_p + schwelle = n - delta*omp_p + iall = delta*rank + rank + 1 + IF ((rank+1)>schwelle) iall = iall + schwelle - rank + + ppos = iall + + RETURN + END + +!> @brief gives number of elements for proc. 'my_rank' +!> @param[in] N number of elements +!> @param[in] my_rank my rank to part the vector (lengths given by N) +!> @param[in] omp_P maximum rank to part the vector +!> @return number of elements for this rank + INTEGER FUNCTION panz(n,my_rank,omp_p) + IMPLICIT NONE + + INTEGER n +! OMP stuff + INTEGER rank, my_rank, omp_p +! tmp variables + INTEGER delta, schwelle + +! checking border + rank = my_rank + IF (rank>(omp_p-1)) rank = omp_p - 1 + IF (rank<0) rank = 0 + + delta = n/omp_p + schwelle = n - delta*omp_p + IF ((rank+1)<(schwelle+1)) delta = delta + 1 + + panz = delta + + RETURN + END + +!> @brief compute position an number of local elements (OpenMP based) +!> @param[in] N number of elements to parting +!> @param[out] tpos start position of local elements +!> @param[out] tanz local number of elements + SUBROUTINE omp_part(n,tpos,tanz) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + + INTEGER n, panz, ppos + EXTERNAL panz, ppos +! thread stuff + INTEGER tpos, tanz + INTEGER my_thd, thd_p + + my_thd = omp_get_his_thread_num() + thd_p = omp_get_num_of_threads() + tanz = panz(n,my_thd,thd_p) + tpos = ppos(n,my_thd,thd_p) + + RETURN + END diff --git a/solve/par_tools.f90 b/solve/par_tools.f90 new file mode 100644 index 0000000..7b7a52b --- /dev/null +++ b/solve/par_tools.f90 @@ -0,0 +1,81 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief deallocate special solver staff, [proza] + SUBROUTINE par_end2() + use arrays + IMPLICIT NONE + +!$OMP master + DEALLOCATE(proza) +!$OMP end master + + RETURN + END + +!> @brief function wrapper for [proza_lock] - avoid side effects +!> @param[in] ProzA_lock processor lock variable +!> @return index of processor +!> @details +!> prove entry (locking)\n + INTEGER FUNCTION par_name(proza_lock) + IMPLICIT NONE + INTEGER proza_lock + +!$OMP flush(ProzA_lock) + par_name = proza_lock + + RETURN + END + +!> @brief wrapper routine to set [proza_lock] - avoid side effects +!> @param[out] ProzA_lock processor lock variable +!> @details +!> disable an entry (locking)\n + SUBROUTINE par_disab(proza_lock) + IMPLICIT NONE + INTEGER proza_lock + + proza_lock = 1 +!$OMP flush(ProzA_lock) + + RETURN + END + +!> @brief initialize/reset [proza_lock] - clean marker of already computed blocks +!> @param[out] ProzA_lock processor lock variable + SUBROUTINE par_reset(proza_lock) + use mod_blocking_size + IMPLICIT NONE + INTEGER proza_lock(bdim_i,bdim_j,bdim_k) + INTEGER i, j, k + + DO k = 1, bdim_k + DO j = 1, bdim_j + DO i = 1, bdim_i + proza_lock(i,j,k) = 0 + END DO + END DO + END DO + + RETURN + END diff --git a/solve/pre_bicgstab.f90 b/solve/pre_bicgstab.f90 new file mode 100644 index 0000000..606e606 --- /dev/null +++ b/solve/pre_bicgstab.f90 @@ -0,0 +1,580 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute the solution for [A]x[x]=[b], [A] general matrix +!> @param[in] N number of elements, vector length, equal for all vectors +!> @param[in,out] x starting-vector [x0], on exit = solution-vector [x] +!> @param[in] b right side, vector [b] +!> @param[in] r0_hat random vector [r0_hat] ^= [r0^] +!> @param[in] ld_lv leading Dimension of 'locTMP' +!> @param[in,out] locTMP space for local vectors, using to exchange data with\n +!> 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R),\n +!> for definitions see more in 'pre_bicgstab.inc' +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It maximum of iterations, counted with 'iter' +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] res0 res0 ^= ||[res0]||, start residuel, given for 'criteria=0' +!> @param[in,out] work control variable : what is to do out of this subroutine,\n +!> see more discription in 'pre_bicgstab.inc',\n +!> on startup should set to 'work=START' +!> @param[in,out] dnrm normalisation vector, temporary use +!> @param[out] ipar integer type help vector - OpenMP "shared" +!> @param[out] rpar floating type point help vector - OpenMP "shared" +!> @param[out] lpar logical type help vector - OpenMP "shared" +!> @details +!> compute the solution for [A]x[x]=[b], [A] general matrix\n +!> make use of [K]=[L_K]*[R_K], [K] is preconditioner for [A]\n +!> - [L_K] : left preconditioner (function : L_PrCo)\n +!> - [R_K] : right preconditioner (function : R_PrCo) +!> +!> Technics :\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread). +!> +!> BiCGStab algorithm :\n +!> before begin : result of [A]x[x] should given in [z]-vector (see locTMP)\n +!> 100 ----------- (... begin ...)\n +!> - [r]:=[b]-[z] ^= [b]-[A]x[x]\n +!> - abbruch(N,r,z,depsilon, ...) ? -> goto 400\n +!> - sigma:=[r0_hat]^T*[r]\n +!> - sigma = 0 ? -> aborting\n +!> - rho:=alpha:=omega=1\n +!> - [v]:=[p]:=0\n +!> - beta:=(sigma/rho)*(alpha/omega)\n +!> - rho:=sigma\n +!> - [p]:=[r]+beta*([p]-omega*[v]) +!> - "solve [K]x[y]=[p]":\n +!> - L_PrCo->[t_pc] [t_pc]:=[L_K^-1]x[p]\n +!> - R_PrCo->[y] [y]:=[R_K^-1]x[t_pc]\n +!> - "myMVP->[v]":\n +!> - [v]:=[A]x[y]\n +!> +!> 200 ----------- (... iterations ...)\n +!> - abbruch(N,r,z,depsilon, ...) ? -> goto 400\n +!> - sigma:=[r0_hat]^T*[v]\n +!> - alpha:=rho/sigma\n +!> - [s]:=[r]-alpha*[v]\n +!> - "solve [K]x[z]=[s]":\n +!> - L_PrCo->[s_pc] [s_pc]:=[L_K^-1]x[s]\n +!> - R_PrCo->[z] [z]:=[R_K^-1]x[s_pc]\n +!> - "myMVP->[t]":\n +!> - [t]:=[A]x[z]\n +!> - L_PrCo->[t_pc] :[t_pc]:=[L_K^-1]x[t]\n +!> +!> 300 ----------- \n +!> - omega:=[t_pc]^T*[s_pc]\n +!> - sigma:=[t_pc]^T*[t_pc]\n +!> - d1:=[r0_hat]^T*[s]\n +!> - d2:=[r0_hat]^T*[t]\n +!> - omega:=omega/sigma\n +!> - [x]:=[x]+alpha*[y]+omega*[z]\n +!> - [r]:=[s]-omega*[t]\n +!> - sigma:=d1-omega*d2\n +!> - sigma = 0 ? -> aborting\n +!> - beta:=(sigma/rho)*(alpha/omega)\n +!> - rho:=sigma\n +!> - [p]:=[r]+beta*([p]-omega*[v])\n +!> - "solve [K]x[y]=[p]":\n +!> - L_PrCo->[t_pc] [t_pc]:=[L_K^-1]x[p]\n +!> - R_PrCo->[y] [y]:=[R_K^-1]x[t_pc]\n +!> - "myMVP->[v]":\n +!> - [v]:=[A]x[y]\n +!> - -> goto 200 (... iterations ...)\n +!> +!> 400 ----------- (... end ...)\n +!> - -> END\n + SUBROUTINE pre_bicgstab(n,x,b,r0_hat,ld_lv,loctmp,depsilon,dnrm, & + max_it,criteria,res0,work,ipar,rpar,lpar) + use mod_OMP_TOOLS + use mod_linfos + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : number of elements of all vector +! ld_lv : leading Dimension for vectors in 'locTMP' + INTEGER n, ld_lv +! vectors [x], [b], [r0_hat] + DOUBLE PRECISION x(max(n,1)), b(max(n,1)) + DOUBLE PRECISION r0_hat(max(n,1)), dnrm(max(n,1)) + +! temporary local variables + DOUBLE PRECISION sigma, beta, omega, res0, d1, d2, de + +! break with enough precision + DOUBLE PRECISION depsilon, p_e_old + INTEGER criteria, p_e_count + +! used external functions + LOGICAL omp_abbruch + EXTERNAL omp_abbruch + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_bicgstab.inc' + DOUBLE PRECISION loctmp(ld_lv,max_loctmp) + +! work : next Work to do + INTEGER work + +! max_It : max iterations + INTEGER max_it + +! first times [Ax] + INTEGER p_first_ax + +! private only for the master thread + INTEGER p_master + + DOUBLE PRECISION d_one + PARAMETER (d_one=1.0D0) + +! blocking staff + INTEGER von, bis + +! for definitions of r,z,s,t,v,p,y,t_pc,s_pc and locTMP see in 'pre_bicgstab.inc' + +! p_* : temporary local private copy of *-variables + DOUBLE PRECISION p_rho, p_alpha + INTEGER p_iter, p_step, p_divide_zero + LOGICAL p_need_ax + + INTRINSIC dsqrt + +! needing saved and shared variables +! iter : count iterations, max_It : max iterations +! step : jump-lable, next line to continue +! divide_zero : control error level +! first_Ax : first times [Ax] +! need_Ax : switch to compute an extra MVP:([A]x[x]) in [z] +! sh_help : openmp-shared space + INTEGER iiter, istep, idivide_zero, ie_count, ifirst_ax + INTEGER rrho, ralpha, re_old, rb_e_old, rsh_help, rsh_vhelp + INTEGER lneed_ax + PARAMETER (iiter=1,istep=2,idivide_zero=3,ie_count=4, & + ifirst_ax=5) + PARAMETER (rrho=1,ralpha=2,re_old=3,rb_e_old=4) +! sh_vhelp needs [4*#threads] entries + PARAMETER (rsh_help=5,rsh_vhelp=6) + PARAMETER (lneed_ax=1) + INTEGER ipar(5) + DOUBLE PRECISION rpar(*) + LOGICAL lpar(1) +! save iter, rho, alpha, need_Ax, step, divide_zero, e_count +! save e_old, b_e_old, first_Ax + + +! shared variables should be private ... + p_iter = ipar(iiter) + p_rho = rpar(rrho) + p_alpha = rpar(ralpha) + p_need_ax = lpar(lneed_ax) + p_step = ipar(istep) + p_divide_zero = ipar(idivide_zero) + p_e_count = ipar(ie_count) + p_e_old = rpar(re_old) + p_first_ax = ipar(ifirst_ax) + de = 2.0D0*rpar(rb_e_old) + +! jump-table + IF (work==start) GO TO 100 + IF (p_step==200) GO TO 200 + IF (p_step==300) GO TO 300 + + WRITE(*,'(A,I3,A)') ' error : no jump label ', p_step, & + ', startup value should be "work=START" !' + GO TO 400 + + +100 CONTINUE + +! need barrier here for fewer data races, because of the init part above +!$OMP barrier +! initialize some 'save'-variables at the beginning of a new system +!aw p_iter = 0 +!aw p_need_Ax = .false. + p_divide_zero = 0 + + p_e_count = 0 + p_e_old = 0.0D0 + rpar(rb_e_old) = 1.0D99 + de = 2.0D0*rpar(rb_e_old) + p_first_ax = 0 + +! rho:=alpha:=omega=1 +! p_rho = d_one + p_alpha = d_one + omega = d_one + +! [r]:=[b]-[z] ^= [b]-[A]x[x] + CALL dcopy(n,b(1),1,loctmp(1,r),1) + CALL daxpy(n,-d_one,loctmp(1,z),1,loctmp(1,r),1) + +! abbruch(N,r,z,depsilon, ...) ? -> goto 400 +! temp. use of 'de' to prove precision + IF (criteria==2) THEN + CALL omp_damax(n,loctmp(1,r),de,rpar(rsh_help)) + ELSE + CALL omp_ddot(n,loctmp(1,r),loctmp(1,r),de,rpar(rsh_vhelp)) +!$OMP master + res0 = dsqrt(de) +!$OMP end master +! need barrier here, because of the next DDOT (rpar-reuse) +!$OMP barrier + END IF + p_need_ax = .TRUE. + p_iter = 1 + + IF (omp_abbruch(de,p_iter,max_it,depsilon,p_need_ax,criteria, & + res0,p_divide_zero,p_e_count,p_e_old)) GO TO 400 + +! initialize some 'save'-variables at the beginning of a new system + p_need_ax = .FALSE. + p_iter = 0 + +! sigma:=[r0_hat]^T*[r] +! d1:=[b]^T*[b]; trivial solution test + CALL omp_2ddot(n,r0_hat(1),loctmp(1,r),sigma,b(1),b(1),d1, & + rpar(rsh_vhelp)) +! impliCit barrier here ... + +! sigma = 0 ? -> aborting, error + CALL test_zero(sigma,1,p_divide_zero) +! d1 = 0 ? -> aborting, trivial solution + CALL test_zero(d1,7,p_divide_zero) + IF (p_divide_zero/=0) GO TO 400 + +! beta:=(sigma/rho)*(alpha/omega) + beta = sigma + +! rho:=sigma + p_rho = sigma + +! [v]:=[p]:=0 + CALL set_dval(n,0.D0,loctmp(1,v)) + CALL set_dval(n,0.D0,loctmp(1,p)) + +! [p]:=[r]+beta*([p]-omega*[v]) + CALL daxpy(n,-omega,loctmp(1,v),1,loctmp(1,p),1) + CALL dscal(n,beta,loctmp(1,p),1) + CALL daxpy(n,d_one,loctmp(1,r),1,loctmp(1,p),1) + +! solve [K]x[y]=[p]: +! L_PrCo->[t_pc] [t_pc]:=[L_K^-1]x[p] +! R_PrCo->[y] [y]:=[R_K^-1]x[t_pc] +! myMVP->[v] :[v]:=[A]x[y] + +! barrier above ... +!$OMP master + work = do_y_p_v +!$OMP end master + p_step = 200 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +200 CONTINUE + +! prepare values for 'omp_abbruch'-function +! temp. use of 'de' to compute precision +! test absulute residuel : ([b]-[A]x[x]) +! [A]x[x] is given in [z] + IF (p_need_ax) THEN + CALL daxpy(n,-d_one,b,1,loctmp(1,z),1) + CALL norm_resid(n,dnrm,x,loctmp(1,z)) + END IF +! impliCit barrier here ... + IF (criteria==2) THEN + IF (p_need_ax) THEN + CALL omp_damax(n,loctmp(1,z),de,rpar(rsh_help)) + ELSE + CALL omp_damax(n,loctmp(1,r),de,rpar(rsh_help)) + END IF +! impliCit barrier here ... +! sigma:=[r0_hat]^T*[v] + CALL omp_ddot(n,r0_hat(1),loctmp(1,v),sigma,rpar(rsh_vhelp)) +! impliCit barrier here ... + ELSE +! sigma:=[r0_hat]^T*[v] +! call omp_ddot(N,r0_hat(1),locTMP(1,v),sigma,rpar(Rsh_vhelp)) + IF (p_need_ax) THEN + CALL omp_2ddot(n,loctmp(1,z),loctmp(1,z),de,r0_hat(1), & + loctmp(1,v),sigma,rpar(rsh_vhelp)) +! impliCit barrier here ... + ELSE + CALL omp_2ddot(n,loctmp(1,r),loctmp(1,r),de,r0_hat(1), & + loctmp(1,v),sigma,rpar(rsh_vhelp)) +! impliCit barrier here ... + END IF + END IF + +! abbruch(N,r,z,depsilon, ...) ? -> goto 400 +! temp. use of 'de' to prove precision + IF (omp_abbruch(de,p_iter,max_it,depsilon,p_need_ax,criteria, & + res0,p_divide_zero,p_e_count,p_e_old)) GO TO 400 + +! sigma:=[r0_hat]^T*[v] +! is compute above ... + +! error prevention + CALL test_zero(sigma,2,p_divide_zero) + +! alpha:=rho/sigma + p_alpha = p_rho/sigma + + +! begin blocking + von = 1 + bis = min(n,int(bl_size/bldiv_bicg(1))) +1 CONTINUE + +! [s]:=[r]-alpha*[v] + CALL dcopy(bis-von+1,loctmp(von,r),1,loctmp(von,s),1) + CALL daxpy(bis-von+1,-p_alpha,loctmp(von,v),1,loctmp(von,s),1) + +! end blocking + von = bis + 1 + bis = min(n,bis+int(bl_size/bldiv_bicg(1))) + IF (von<=n) GO TO 1 + + +! solve [K]x[z]=[s]: +! L_PrCo->[s_pc] [s_pc]:=[L_K^-1]x[s] +! R_PrCo->[z] [z]:=[R_K^-1]x[s_pc] +! myMVP->[t] :[t]:=[A]x[z] +! L_PrCo->[t_pc] :[t_pc]:=[L_K^-1]x[t] + +! barrier above ... (in omp_ddot) +!$OMP master + work = do_z_s_t +!$OMP end master + p_step = 300 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +300 CONTINUE + +! omega:=[t_pc]^T*[s_pc] +! call omp_ddot(N,locTMP(1,t_pc),locTMP(1,s_pc),omega,rpar(Rsh_vhelp)) + +! sigma:=[t_pc]^T*[t_pc] +! call omp_ddot(N,locTMP(1,t_pc),locTMP(1,t_pc),sigma,rpar(Rsh_vhelp)) + +! d1:=[r0_hat]^T*[s] +! call omp_ddot(N,r0_hat(1),locTMP(1,s),d1,rpar(Rsh_vhelp)) + +! d2:=[r0_hat]^T*[t] +! call omp_ddot(N,r0_hat(1),locTMP(1,t),d2,rpar(Rsh_vhelp)) + + + CALL omp_4ddot(n,loctmp(1,t_pc),loctmp(1,s_pc),omega, & + loctmp(1,t_pc),loctmp(1,t_pc),sigma,r0_hat(1),loctmp(1,s), & + d1,r0_hat(1),loctmp(1,t),d2,rpar(rsh_vhelp)) +! impliCit barrier here ... + +! error prevention + CALL test_zero(sigma,3,p_divide_zero) + +! omega:=omega/sigma + omega = omega/sigma + +! change computing order ... + +! sigma:=d1-omega*d2 + sigma = d1 - omega*d2 + +! sigma = 0 ? -> aborting + CALL test_zero(sigma,4,p_divide_zero) + +! error prevention + CALL test_zero(p_rho,5,p_divide_zero) + CALL test_zero(omega,6,p_divide_zero) + +! beta:=(sigma/rho)*(alpha/omega) + beta = (sigma*p_alpha)/(p_rho*omega) + + +! begin blocking + von = 1 + bis = min(n,int(bl_size/bldiv_bicg(2))) +2 CONTINUE + +! [x]:=[x]+alpha*[y]+omega*[z] + CALL daxpy(bis-von+1,p_alpha,loctmp(von,y),1,x(von),1) + CALL daxpy(bis-von+1,omega,loctmp(von,z),1,x(von),1) + +! [r]:=[s]-omega*[t] + CALL dcopy(bis-von+1,loctmp(von,s),1,loctmp(von,r),1) + CALL daxpy(bis-von+1,-omega,loctmp(von,t),1,loctmp(von,r),1) + +! [p]:=[r]+beta*([p]-omega*[v]) + CALL daxpy(bis-von+1,-omega,loctmp(von,v),1,loctmp(von,p),1) + CALL dscal(bis-von+1,beta,loctmp(von,p),1) + CALL daxpy(bis-von+1,d_one,loctmp(von,r),1,loctmp(von,p),1) + +! end blocking + von = bis + 1 + bis = min(n,bis+int(bl_size/bldiv_bicg(2))) + IF (von<=n) GO TO 2 + + +! rho:=sigma + p_rho = sigma + +! iteration counting (+2 Matrix-Vector-Products) + p_iter = p_iter + 1 + +! if division by zero detected, try to testing for good precision +! can be disabled !!! + IF (p_divide_zero/=0) p_need_ax = .TRUE. + +! solve [K]x[y]=[p]: +! L_PrCo->[t_pc] [t_pc]:=[L_K^-1]x[p] +! R_PrCo->[y] [y]:=[R_K^-1]x[t_pc] +! myMVP->[v] :[v]:=[A]x[y] + +!$OMP master + work = do_y_p_v + +! need a second MVP, compute ([A]x[x]) in [z] + IF (p_need_ax) work = more_y_p_v +!$OMP end master + p_step = 200 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +400 CONTINUE + +! -> END + +! restore best [x] value + IF (rpar(rb_e_old)<p_e_old .AND. rpar(rb_e_old)<de) THEN + CALL dcopy(n,loctmp(1,best),1,x,1) +! so "b_e_old" will not changed later by the master + p_e_old = rpar(rb_e_old) +!$OMP master + IF (linfos(4)>=1) THEN + IF (criteria==2) THEN + WRITE(*,'(1A,1e20.13,1A)',advance='NO') ', {', & + rpar(rb_e_old), '}' + ELSE + WRITE(*,'(1A,1e20.13,1A)',advance='NO') ', {', & + dsqrt(rpar(rb_e_old)), '}' + END IF + END IF +!$OMP end master + END IF + +! need barrier before ... +!$OMP master + work = fine +!$OMP end master + p_step = 0 + + IF (p_divide_zero/=0) THEN +!$OMP master + work = abort + IF (p_divide_zero==1) THEN + WRITE(*,*) ' ' + WRITE(*,'(A)') ' warning: ([r^]^T*[r]) near Null' + ELSE IF (p_divide_zero==7) THEN + IF (linfos(4)>=0) THEN + WRITE(*,*) ' ' + WRITE(*,'(2A)') ' warning: trivial solution, no boundary'& + , ' condition different from zero defined' + END IF + ELSE + IF (linfos(4)>=0) THEN + WRITE(*,*) ' ' + WRITE(*,'(A,I2)') ' warning: Division by zero with code:'& + , p_divide_zero + END IF + END IF +!$OMP end master + END IF +! no barrier here ... need it later ... + +!$OMP master + IF (linfos(4)>=1) THEN +!$ write(*,'(1A,1I4)',ADVANCE='NO') ', ',OMP_GET_NUM_of_THREADS() +!$ write(*,'(1A)',ADVANCE='NO') ' threads used' + IF (p_iter>max_it) THEN + WRITE(*,'(A,I5,A)') ', Number of Iterations: ', p_iter, & + ':MAXIMUM (BiCGStab)' + ELSE + WRITE(*,'(A,I5,A)') ', Number of Iterations: ', p_iter, & + ' (BiCGStab)' + END IF + END IF +!$OMP end master + +1000 CONTINUE + + IF (p_need_ax .AND. p_divide_zero==0 .AND. p_first_ax>=0) & + p_first_ax = p_first_ax + 1 + +! save best [x] value + p_master = 0 + IF (p_e_old<rpar(rb_e_old) .OR. p_first_ax==3) THEN +! save [x] + CALL dcopy(n,x,1,loctmp(1,best),1) + IF (p_first_ax==3) p_first_ax = -1 +!$OMP master + p_master = 1 +!$OMP end master + END IF + +! Danger : here is an important syncronistaion for consistent view +! of 'work' and all save variables on exit ... +!$OMP barrier + +!$OMP master + IF (p_master==1) rpar(rb_e_old) = p_e_old +! private variables should be shared to save ... + ipar(iiter) = p_iter + rpar(rrho) = p_rho + rpar(ralpha) = p_alpha + lpar(lneed_ax) = p_need_ax + ipar(istep) = p_step + ipar(idivide_zero) = p_divide_zero + ipar(ie_count) = p_e_count + rpar(re_old) = p_e_old + ipar(ifirst_ax) = p_first_ax +!$OMP end master + + RETURN + END diff --git a/solve/pre_bicgstab.inc b/solve/pre_bicgstab.inc new file mode 100644 index 0000000..6ff6e39 --- /dev/null +++ b/solve/pre_bicgstab.inc @@ -0,0 +1,86 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +! +! K=L_K*R_K : preconditioner +! +! Constant : aborting, ([r0_hat]^T*[r])=0 + integer ABORT +! +! Constant : at the beginning of a new system + integer START +! +! Constant : preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[A]x[y] + integer Do_y_p_v +! +! Constant : preconditioner [z]:=[K^-1]x[s], +! preconditioner [s_pc]:=[L_K^-1]x[s], +! matrix-vector product [t]:=[A]x[z], +! preconditioner [t_pc]:=[L_K^-1]x[t] + integer Do_z_s_t +! +! Constant : preconditioner [y]:=[K^-1]x[p], +! matrix-vector product [v]:=[A]x[y], +! matrix-vector product [z]:=[A]x[x] for advanced precision + integer more_y_p_v +! +! Constant : nothing to do anymore ... + integer FINE +! + parameter (ABORT =-1) + parameter (START = 0) + parameter (Do_y_p_v = 1) + parameter (Do_z_s_t = 2) + parameter (more_y_p_v = 3) + parameter (FINE = 4) + +! +! offsets for temporary vectors saved in [locTMP] +! ld_lv : leading dimension (local number of elements) +! locTMP(1,1) ^= [b_hat] (only for EST) +! locTMP(1,2) ^= [r0_tilde] (only for EST) +! locTMP(1,3) ^= [r] +! locTMP(1,4) ^= [z] +! locTMP(1,5) ^= [s] +! locTMP(1,6) ^= [t] +! locTMP(1,7) ^= [v] +! locTMP(1,8) ^= [p] +! locTMP(1,9) ^= [y] +! locTMP(1,10) ^= [t_pc] +! locTMP(1,11) ^= [s_pc] +! locTMP(1,12)^= [mt] (only for EST) +! locTMP(1,13)^= [best] X value + integer b_hat,r0_tilde,r,z,s,t,v,p,y,t_pc,s_pc,mt,best + parameter(b_hat=1) + parameter(r0_tilde=2) + parameter(r=3) + parameter(z=4) + parameter(s=5) + parameter(t=6) + parameter(v=7) + parameter(p=8) + parameter(y=9) + parameter(t_pc=10) + parameter(s_pc=11) + parameter(mt=12) + parameter(best=13) diff --git a/solve/pre_cg.f90 b/solve/pre_cg.f90 new file mode 100644 index 0000000..5995ff0 --- /dev/null +++ b/solve/pre_cg.f90 @@ -0,0 +1,540 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief compute the solution for [A]x[x]=[b], [A] sym.pos.def. matrix +!> @param[in] N number of elements, vector length, equal for all vectors +!> @param[in,out] x starting-vector [x0], on exit = solution-vector [x] +!> @param[in] b right side, vector [b] +!> @param[in] ld_lv leading Dimension of 'locTMP' +!> @param[in,out] locTMP space for local vectors, using to exchange data with\n +!> 'matrix-vector-product'(MVP) and 'pre-conditioners'(L/R),\n +!> for definitions see more in 'pre_bicgstab.inc' +!> @param[in] depsilon precision criteria to break iterations +!> @param[in] max_It maximum of iterations, counted with 'iter' +!> @param[in] criteria precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] res0 res0 ^= ||[res0]||, start residuel, given for 'criteria=0' +!> @param[in,out] work control variable : what is to do out of this subroutine,\n +!> see more discription in 'pre_bicgstab.inc',\n +!> on startup should set to 'work=START' +!> @param[in,out] dnrm normalisation vector, temporary use +!> @param[out] ipar integer type help vector - OpenMP "shared" +!> @param[out] rpar floating type point help vector - OpenMP "shared" +!> @param[out] lpar logical type help vector - OpenMP "shared" +!> @details +!> compute the solution for [A]x[x]=[b], [A] sym.pos.def. matrix\n +!> make use of [K] as a preconditioner for [A], (function : myPrCo)\n +!> Technics :20;\n +!> - use reverse communication technics.\n +!> each vector should be dense full without any hole,\n +!> ( you can copy your elements from your structure to a \n +!> temporary dense full vector, befor you use this algorithm \n +!> and give the correct number of elements in 'N' ).\n +!> if you have setup all vectors by a specific composition,\n +!> each vector (x,b,r,...) on the same thread should use\n +!> the same composition (same structure for all vectors on\n +!> one thread). +!> +!> CG algorithm :\n +!> before begin : result of [A]x[x] should given in [s]-vector (see locTMP)\n +!> 100 ----------- (... begin ...)\n +!> - [r]:=[b]-[s]\n +!> - abbruch(N,r,depsilon, ...) ? -> goto 400\n +!> - [p]:=[q]:=0\n +!> - beta:=0\n +!> - "solve [K][z]=[r]":\n +!> - myPrCo->[z] [z]:=[K^-1]x[r]\n +!> - "myMVP->[s]":\n +!> - [s]:=[A]x[z]\n +!> +!> 200 ----------- \n +!> - sigma:=([r]^T*[z])\n +!> - mu:=([s]^T*[z])\n +!> - alpha:=sigma/mu\n +!> - [p]:=[z]+beta*[p]\n +!> - [q]:=[s]+beta*[q]\n +!> - [x]:=[x]+alpha*[p]\n +!> - [r]:=[r]-alpha*[q]\n +!> - "solve [K][z]=[r]":\n +!> - myPrCo->[z] [z]:=[K^-1]x[r]\n +!> - "myMVP->[s]":\n +!> - [s]:=[A]x[z]\n +!> +!> 300 ----------- (... iterations ...)\n +!> - abbruch(N,r,depsilon, ...) ? -> goto 400\n +!> - sigma_new:=([r]^T*[z])\n +!> - mu:=([s]^T*[z])\n +!> - beta:=sigma_new/sigma\n +!> - sigma:=sigma_new\n +!> - alpha:=sigma/(mu-sigma*beta/alpha)\n +!> - [p]:=[z]+beta*[p]\n +!> - [q]:=[s]+beta*[q]\n +!> - [x]:=[x]+alpha*[p]\n +!> - [r]:=[r]-alpha*[q]\n +!> - "solve [K][z]=[r]":\n +!> - myPrCo->[z] [z]:=[K^-1]x[r]\n +!> - "myMVP->[s]":\n +!> - [s]:=[A]x[z]\n +!> - -> goto 300 (... iterations ...)\n +!> +!> 400 ----------- (... end ...)\n +!> - -> END\n + SUBROUTINE pre_cg(n,x,b,ld_lv,loctmp,depsilon,dnrm,max_it, & + criteria,res0,work,ipar,rpar,lpar) + use mod_OMP_TOOLS + use mod_linfos + use mod_blocking_size + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + +! N : number of elements of all vector +! ld_lv : leading Dimension for vectors in 'locTMP' + INTEGER n, ld_lv +! vectors [x], [b] + DOUBLE PRECISION x(max(n,1)), b(max(n,1)), dnrm(max(n,1)) + +! temporary local variables + DOUBLE PRECISION mu, sigma_new, enough, res0 + +! break with enough precision + DOUBLE PRECISION depsilon, p_e_old + INTEGER criteria, p_e_count + +! used external functions + LOGICAL omp_abbruch + EXTERNAL omp_abbruch + +! definitions of 'work' and 'locTMP' + INCLUDE 'pre_cg.inc' + DOUBLE PRECISION loctmp(ld_lv,max_loctmp) + +! work : next Work to do + INTEGER work + +! max_It : max iterations + INTEGER max_it + +! first times [Ax] + INTEGER p_first_ax + +! private only for the master thread + INTEGER p_master + + DOUBLE PRECISION d_one, dzero + PARAMETER (d_one=1.0D0,dzero=0.0D0) + +! blocking staff + INTEGER von, bis + +! for definitions of r,z,s,p,q,v and locTMP see in 'pre_cg.inc' + +! p_* : temporary local private copy of *-variables + DOUBLE PRECISION p_beta, p_sigma, p_alpha + INTEGER p_iter, p_step, p_divide_zero + LOGICAL p_need_ax + + INTRINSIC dsqrt + +! needing saved and shared variables +! iter : count iterations, max_It : max iterations +! step : jump-lable, next line to continue +! divide_zero : control error level +! first_Ax : first times [Ax] +! need_Ax : switch to compute an extra MVP:([A]x[x]) in [z] +! sh_help : openmp-shared space + INTEGER iiter, istep, idivide_zero, ie_count, ifirst_ax + INTEGER rbeta, rsigma, ralpha, re_old, rb_e_old, rsh_help, & + rsh_vhelp + INTEGER lneed_ax + PARAMETER (iiter=1,istep=2,idivide_zero=3,ie_count=4, & + ifirst_ax=5) + PARAMETER (rbeta=1,rsigma=2,ralpha=3,re_old=4,rb_e_old=5) +! sh_vhelp needs [4*#threads] entries + PARAMETER (rsh_help=6,rsh_vhelp=7) + PARAMETER (lneed_ax=1) + INTEGER ipar(5) + DOUBLE PRECISION rpar(*) + LOGICAL lpar(1) +! save iter, need_Ax, step, divide_zero, beta, sigma, alpha +! save e_Count, e_old, b_e_old, first_Ax + + +! shared variables should be private ... + p_iter = ipar(iiter) + p_need_ax = lpar(lneed_ax) + p_step = ipar(istep) + p_divide_zero = ipar(idivide_zero) + p_beta = rpar(rbeta) + p_sigma = rpar(rsigma) + p_alpha = rpar(ralpha) + p_e_count = ipar(ie_count) + p_e_old = rpar(re_old) + p_first_ax = ipar(ifirst_ax) + enough = 2.0D0*rpar(rb_e_old) + +! jump-table + IF (work==start) GO TO 100 + IF (p_step==200) GO TO 200 + IF (p_step==300) GO TO 300 + + WRITE(*,*) & + 'error : no jump lable, startup value should work=START' + GO TO 400 + + +100 CONTINUE + +! need barrier here for fewer data races, because of the init above ... +!$OMP barrier +! initialize some 'save'-variables at the beginning of a new system +!aw p_iter = 0 +!aw p_need_Ax = .false. + p_divide_zero = 0 + + p_e_count = 0 + p_e_old = 0.0D0 + rpar(rb_e_old) = 1.0D99 + enough = 2.0D0*rpar(rb_e_old) + p_first_ax = 0 + +! beta:=0 + p_beta = dzero + +! [r]:=[b]-[s] + CALL dcopy(n,b(1),1,loctmp(1,r),1) + CALL daxpy(n,-d_one,loctmp(1,s),1,loctmp(1,r),1) + +! abbruch(iter,r,depsilon, ...) ? -> goto 400 +! temp. use of 'enough' to prove precision + IF (criteria==2) THEN + CALL omp_damax(n,loctmp(1,r),enough,rpar(rsh_help)) + ELSE + CALL omp_ddot(n,loctmp(1,r),loctmp(1,r),enough, & + rpar(rsh_vhelp)) + res0 = dsqrt(enough) + END IF + p_need_ax = .TRUE. + p_iter = 1 + IF (omp_abbruch(enough,p_iter,max_it,depsilon,p_need_ax, & + criteria,res0,p_divide_zero,p_e_count,p_e_old)) GO TO 400 + +! initialize some 'save'-variables at the beginning of a new system + p_need_ax = .FALSE. + p_iter = 0 + +! [p]:=[q]:=0 + CALL set_dval(n,0.D0,loctmp(1,p)) + CALL set_dval(n,0.D0,loctmp(1,q)) + +! mu:= [b]^T*[b], trivial solution test + CALL omp_ddot(n,b(1),b(1),mu,rpar(rsh_vhelp)) + +! mu = 0 ? aborting, trivial solution + CALL test_zero(mu,4,p_divide_zero) + IF (p_divide_zero/=0) GO TO 400 + +! solve [K][z]=[r]: +! myPrCo->[z] [z]:=[K^-1]x[r] +! myMVP->[s] :[s]:=[A]x[z] + +! barrier above ... +!$OMP master + work = mvp +!$OMP end master + p_step = 200 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +200 CONTINUE + +! sigma:=([r]^T*[z]) +! call omp_ddot(N,locTMP(1,r),locTMP(1,z),sigma,rpar(Rsh_vhelp)) + +! mu:=([s]^T*[z]) +! call omp_ddot(N,locTMP(1,s),locTMP(1,z),mu,rpar(Rsh_vhelp)) + + CALL omp_2ddot(n,loctmp(1,r),loctmp(1,z),p_sigma,loctmp(1,s), & + loctmp(1,z),mu,rpar(rsh_vhelp)) +! implicit barrier here ... + +! error prevention + CALL test_zero(mu,1,p_divide_zero) + +! alpha:=sigma/mu + p_alpha = p_sigma/mu + +! [p]:=[z]+beta*[p] + CALL dscal(n,p_beta,loctmp(1,p),1) + CALL daxpy(n,d_one,loctmp(1,z),1,loctmp(1,p),1) + +! [q]:=[s]+beta*[q] + CALL dscal(n,p_beta,loctmp(1,q),1) + CALL daxpy(n,d_one,loctmp(1,s),1,loctmp(1,q),1) + +! [x]:=[x]+alpha*[p] + CALL daxpy(n,p_alpha,loctmp(1,p),1,x(1),1) + +! [r]:=[r]-alpha*[q] + CALL daxpy(n,-p_alpha,loctmp(1,q),1,loctmp(1,r),1) + +! solve [K][z]=[r]: +! myPrCo->[z] [z]:=[K^-1]x[r] +! myMVP->[s] :[s]:=[A]x[z] + +!$OMP barrier +! need barrier here ... +!$OMP master + work = mvp +!$OMP end master + p_step = 300 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +300 CONTINUE + +! preparing values for 'omp_abbruch'-function +! temp. use of 'enough' to compute precision + IF (p_need_ax) THEN +! test absulute residuel : ([b]-[A]x[x]) +! [A]x[x] is given in [v] +! compute ([A]x[x]-[b]) instead above + CALL daxpy(n,-d_one,b,1,loctmp(1,v),1) + CALL norm_resid(n,dnrm,x,loctmp(1,v)) + IF (criteria==2) THEN + CALL omp_damax(n,loctmp(1,v),enough,rpar(rsh_help)) +! implicit barrier here ... + +! sigma_new:=([r]^T*[z]) +! mu:=([s]^T*[z]) + CALL omp_2ddot(n,loctmp(1,r),loctmp(1,z),sigma_new, & + loctmp(1,s),loctmp(1,z),mu,rpar(rsh_vhelp)) +! implicit barrier here ... + ELSE +! call omp_ddot(N,locTMP(1,v),locTMP(1,v),enough,rpar(Rsh_vhelp)) + +! sigma_new:=([r]^T*[z]) +! mu:=([s]^T*[z]) + CALL omp_3ddot(n,loctmp(1,v),loctmp(1,v),enough, & + loctmp(1,r),loctmp(1,z),sigma_new,loctmp(1,s), & + loctmp(1,z),mu,rpar(rsh_vhelp)) +! implicit barrier here ... + END IF + ELSE +! test [r] instead of residuel + IF (criteria==2) THEN + CALL omp_damax(n,loctmp(1,r),enough,rpar(rsh_help)) +! implicit barrier here ... + +! sigma_new:=([r]^T*[z]) +! mu:=([s]^T*[z]) + CALL omp_2ddot(n,loctmp(1,r),loctmp(1,z),sigma_new, & + loctmp(1,s),loctmp(1,z),mu,rpar(rsh_vhelp)) +! implicit barrier here ... + ELSE +! call omp_ddot(N,locTMP(1,r),locTMP(1,r),enough,rpar(Rsh_vhelp)) + +! sigma_new:=([r]^T*[z]) +! mu:=([s]^T*[z]) + CALL omp_3ddot(n,loctmp(1,r),loctmp(1,r),enough, & + loctmp(1,r),loctmp(1,z),sigma_new,loctmp(1,s), & + loctmp(1,z),mu,rpar(rsh_vhelp)) +! implicit barrier here ... + END IF + END IF + +! abbruch(iter,r,depsilon, ...) ? -> goto 400 +! temp. use of 'enough' to prove precision + IF (omp_abbruch(enough,p_iter,max_it,depsilon,p_need_ax, & + criteria,res0,p_divide_zero,p_e_count,p_e_old)) GO TO 400 + +! sigma_new:=([r]^T*[z]) +! is compute above ... + +! mu:=([s]^T*[z]) +! is compute above ... + +! error prevention + CALL test_zero(p_sigma,2,p_divide_zero) + +! beta:=sigma_new/sigma + p_beta = sigma_new/p_sigma + +! sigma:=sigma_new + p_sigma = sigma_new + +! alpha:=sigma/(mu-sigma*beta/alpha) + p_alpha = mu - p_sigma*p_beta/p_alpha + +! error prevention + CALL test_zero(p_alpha,3,p_divide_zero) + + p_alpha = p_sigma/p_alpha + +! iteration counting + p_iter = p_iter + 1 + + +! begin blocking + von = 1 + bis = min(n,int(bl_size/bldiv_cg)) +1 CONTINUE + +! [p]:=[z]+beta*[p] + CALL dscal(bis-von+1,p_beta,loctmp(von,p),1) + CALL daxpy(bis-von+1,d_one,loctmp(von,z),1,loctmp(von,p),1) + +! [q]:=[s]+beta*[q] + CALL dscal(bis-von+1,p_beta,loctmp(von,q),1) + CALL daxpy(bis-von+1,d_one,loctmp(von,s),1,loctmp(von,q),1) + +! [x]:=[x]+alpha*[p] + CALL daxpy(bis-von+1,p_alpha,loctmp(von,p),1,x(von),1) + +! [r]:=[r]-alpha*[q] + CALL daxpy(bis-von+1,-p_alpha,loctmp(von,q),1,loctmp(von,r),1) + +! end blocking + von = bis + 1 + bis = min(n,bis+int(bl_size/bldiv_cg)) + IF (von<=n) GO TO 1 + + +! solve [K][z]=[r]: +! myPrCo->[z] [z]:=[K^-1]x[r] +! myMVP->[s] :[s]:=[A]x[z] + +! barrier above ... (in omp_ddot) +!$OMP master + work = mvp +! need a second MVP, compute ([A]x[x]) in [z] + IF (p_need_ax) work = mvpx +!$OMP end master + p_step = 300 +! no barrier here ... need barrier later ... + + GO TO 1000 + + +400 CONTINUE + +! -> END + +! restore best [x] value + IF (rpar(rb_e_old)<p_e_old .AND. rpar(rb_e_old)<enough) THEN + CALL dcopy(n,loctmp(1,best),1,x,1) +! so "b_e_old" will not changed later by the master + p_e_old = rpar(rb_e_old) +!$OMP master + IF (linfos(4)>=1) THEN + IF (criteria==2) THEN + WRITE(*,'(1A,1e20.13,1A)',advance='NO') ', {', & + rpar(rb_e_old), '}' + ELSE + WRITE(*,'(1A,1e20.13,1A)',advance='NO') ', {', & + dsqrt(rpar(rb_e_old)), '}' + END IF + END IF +!$OMP end master + END IF + +! need barrier before ... +!$OMP master + work = fine +!$OMP end master + p_step = 0 + + IF (p_divide_zero/=0) THEN +!$OMP master + work = abort + IF (linfos(4)>=0) THEN + IF (p_divide_zero==4) THEN + WRITE(*,*) ' ' + WRITE(*,'(2A)') ' warning: trivial solution, no boundary'& + , ' condition different from zero' + ELSE + WRITE(*,*) ' ' + WRITE(*,'(A,I2)') ' warning: Division by zero with code:'& + , p_divide_zero + END IF + END IF +!$OMP end master + END IF +! no barrier here ... need it later ... + +!$OMP master + IF (linfos(4)>=1) THEN +!$ write(*,'(1A,1I4)',ADVANCE='NO') ', ',OMP_GET_NUM_of_THREADS() +!$ write(*,'(1A)',ADVANCE='NO') ' threads used' + IF (p_iter>max_it) THEN + WRITE(*,'(A,I5,A)') ', Number of Iterations: ', p_iter, & + ':MAXIMUM (CG)' + ELSE + WRITE(*,'(A,I5,A)') ', Number of Iterations: ', p_iter, & + ' (CG)' + END IF + END IF +!$OMP end master + +1000 CONTINUE + + IF (p_need_ax .AND. p_divide_zero==0 .AND. p_first_ax>=0) & + p_first_ax = p_first_ax + 1 + +! save best [x] value + p_master = 0 + IF (p_e_old<rpar(rb_e_old) .OR. p_first_ax==3) THEN +! save [x] + CALL dcopy(n,x,1,loctmp(1,best),1) + IF (p_first_ax==3) p_first_ax = -1 +!$OMP master + p_master = 1 +!$OMP end master + END IF + +! Danger : here is an important syncronistaion for consistent view +! of 'work' and all save variables on exit ... +!$OMP barrier + +!$OMP master + IF (p_master==1) rpar(rb_e_old) = p_e_old +! private variables should be shared to save ... + ipar(iiter) = p_iter + lpar(lneed_ax) = p_need_ax + ipar(istep) = p_step + ipar(idivide_zero) = p_divide_zero + rpar(rbeta) = p_beta + rpar(rsigma) = p_sigma + rpar(ralpha) = p_alpha + ipar(ie_count) = p_e_count + rpar(re_old) = p_e_old + ipar(ifirst_ax) = p_first_ax +!$OMP end master + + RETURN + END diff --git a/solve/pre_cg.inc b/solve/pre_cg.inc new file mode 100644 index 0000000..76642a8 --- /dev/null +++ b/solve/pre_cg.inc @@ -0,0 +1,66 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +! +! Constant : at the beginning of a new system + integer START +! +! Constant : Matrix-Vector-Product [v]:=[A]x[s] + integer MVP +! +! Constant : two Matrix-Vector-Product [v]:=[A]x[s] & [z]:=[A]x[x] + integer MVPx +! +! Constant : nothing to do anymore ... + integer FINE +! +! Constant : must break + integer ABORT +! + parameter (START = 0) + parameter (MVP = 1) + parameter (MVPx = 2) + parameter (FINE = 3) + parameter (ABORT = 4) + +! +! offsets for temporary vectors saved in [locTMP] +! ld_lv : leading dimensions (lokal number of elements) +! locTMP(1,1) ^= [b_hat] +! locTMP(1,2) ^= [r] +! locTMP(1,3) ^= [z] +! locTMP(1,4) ^= [s] +! locTMP(1,5) ^= [p] +! locTMP(1,6) ^= [q] +! locTMP(1,7) ^= [v] +! locTMP(1,8) ^= [mt] (only for EST) +! locTMP(1,9) ^= [best] X value + integer b_hat,r,z,s,p,q,v,mt,best + parameter(b_hat=1) + parameter(r=2) + parameter(z=3) + parameter(s=4) + parameter(p=5) + parameter(q=6) + parameter(v=7) + parameter(mt=8) + parameter(best=9) diff --git a/solve/preconditioners.f90 b/solve/preconditioners.f90 new file mode 100644 index 0000000..7a33035 --- /dev/null +++ b/solve/preconditioners.f90 @@ -0,0 +1,76 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief preconditioner "dummy" routine, no preconditioning (copy instead) +!> @param[in] N length of all vectors +!> @param[in] r vector [r] +!> @param[out] z vector [z] +!> @details +!> compute [z], the solution of [K]x[z]=[r]\n +!> [K] is substitude from [A] and work as a preconditioner\n +!> here simple example : only copy [z]:=[r]\n + SUBROUTINE myprco(n,r,z) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vectors r,z + INTEGER n +! vectors [r], [z] + DOUBLE PRECISION r(*), z(*) +! thread-stuff + INTEGER tpos, tanz + + CALL omp_part(n,tpos,tanz) +! very simple Pre-Cond. + CALL dcopy(tanz,r(tpos),1,z(tpos),1) + RETURN + END + +!> @brief simple diagonal preconditioner +!> @param[in] N length of all vectors +!> @param[in] r vector [r] +!> @param[in] D diagonal vector for preconditioning +!> @param[out] z vector [z] +!> @details +!> compute [z], the solution of [K]x[z]=[r]\n +!> [K] is substitude from [A] and work as a preconditioner\n +!> here simple example : [z]:=[r]/[d]\n + SUBROUTINE diagprco(n,d,r,z) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! N : length of all vectors r,z + INTEGER n, i +! vectors [r], [z] + DOUBLE PRECISION r(n), z(n), d(n) +! thread-stuff + INTEGER tpos, tanz + + CALL omp_part(n,tpos,tanz) +! works if there are not NULL-elements in [D] +! very simple Pre-Cond. + DO i = tpos, tpos + tanz - 1 +!AW z(i)=r(i)/D(i) + IF (d(i)/=0.0D0) z(i) = r(i)/d(i) + END DO + RETURN + END diff --git a/solve/prepare_solve.f90 b/solve/prepare_solve.f90 new file mode 100644 index 0000000..82ea88b --- /dev/null +++ b/solve/prepare_solve.f90 @@ -0,0 +1,317 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief setup ILU(0) preconditioner diagonal [UD] +!> @param[in] NI lengths of I dimension of local matrix [M] +!> @param[in] NJ lengths of J dimension of local matrix [M] +!> @param[in] NK lengths of K dimension of local matrix [M] +!> @param[in] LA 1. diagonal of the system matrix [M] +!> @param[in] LB 2. diagonal of the system matrix [M] +!> @param[in] LC 3. diagonal of the system matrix [M] +!> @param[in] LD 4. diagonal of the system matrix [M] +!> @param[in] LE 5. diagonal of the system matrix [M] +!> @param[in] LF 6. diagonal of the system matrix [M] +!> @param[in] LG 7. diagonal of the system matrix [M] +!> @param[out] LUD helper diagonal elements for preconditioning, vector [UD] + SUBROUTINE prepare_ilu(ni,nj,nk,la,lb,lc,ld,le,lf,lg,lud) + use mod_linfos + IMPLICIT NONE + INTEGER ni, nj, nk + INTEGER i, j, k + DOUBLE PRECISION la(ni,nj,nk), lb(ni,nj,nk), lc(ni,nj,nk) + DOUBLE PRECISION ld(ni,nj,nk), le(ni,nj,nk), lf(ni,nj,nk) + DOUBLE PRECISION lg(ni,nj,nk) + DOUBLE PRECISION lud(ni,nj,nk), tmp, tmp_ud, tmp_d, tmp_bug + INTEGER tnul, tnul_ + LOGICAL test_null, lintel_dummy + EXTERNAL test_null + + + tmp_bug = 0.D0 +!$OMP master + CALL dcopy(ni*nj*nk,ld,1,lud,1) + + DO k = 1, nk + DO j = 1, nj + DO i = 1, ni + tmp_ud = lud(i,j,k) + tnul = 0 + CALL test_zero(tmp_ud,1,tnul) + tmp_d = ld(i,j,k) + tnul_ = 0 + CALL test_zero(tmp_d,1,tnul_) + + IF ((tnul_/=1) .AND. (tnul/=1)) THEN + tmp = 1.0D0/tmp_ud + + IF (i<ni) THEN +!buggy lUD(i+1,j,k) = lUD(i+1,j,k) -lC(i+1,j,k)*tmp*lE(i,j,k) + tmp_bug = lc(i+1,j,k)*tmp + lud(i+1,j,k) = lud(i+1,j,k) - tmp_bug*le(i,j,k) + END IF + IF (j<nj) THEN +!buggy lUD(i,j+1,k) = lUD(i,j+1,k) -lB(i,j+1,k)*tmp*lF(i,j,k) + tmp_bug = lb(i,j+1,k)*tmp + lud(i,j+1,k) = lud(i,j+1,k) - tmp_bug*lf(i,j,k) + END IF + IF (k<nk) THEN +!buggy lUD(i,j,k+1) = lUD(i,j,k+1) -lA(i,j,k+1)*tmp*lG(i,j,k) + tmp_bug = la(i,j,k+1)*tmp + lud(i,j,k+1) = lud(i,j,k+1) - tmp_bug*lg(i,j,k) + END IF + ELSE + WRITE(*,'(A,3I5,A,2e15.8)') & + 'error in prepare_solve.f90: main diagonal element equal to zero at ', i, & + j, k, '=', ld(i,j,k), lud(i,j,k) + STOP + END IF + END DO + END DO + END DO +!$OMP end master +!$OMP barrier + +! break intel-compiler optimisation, +! to avoid numerical instabilities for +! lUD(i+1,j,k) = lUD(i+1,j,k) - [ lC(i+1,j,k)*tmp ] *lE(i,j,k) +! lUD(i,j+1,k) = lUD(i,j+1,k) - [ lB(i,j+1,k)*tmp ] *lF(i,j,k) +! lUD(i,j,k+1) = lUD(i,j,k+1) - [ lA(i,j,k+1)*tmp ] *lG(i,j,k) + lintel_dummy = test_null(tmp_bug) + +! faster ... +!$OMP do schedule(static) + DO k = 1, nk + DO j = 1, nj + DO i = 1, ni +! for UD, an near NULL criteria is saver + tmp_ud = lud(i,j,k) + tnul = 0 + CALL test_zero(tmp_ud,1,tnul) + IF ((ld(i,j,k)/=0.0D0) .AND. (tnul/=1)) THEN + lud(i,j,k) = 1.0D0/tmp_ud + END IF + END DO + END DO + END DO +!$OMP end do nowait + + RETURN + END + +!> @brief copy "private", distribute the "shared" [full] vector into the [local] "private" block area +!> @param[in] NI lengths of I dimension of local matrix [M] +!> @param[in] NJ lengths of J dimension of local matrix [M] +!> @param[in] NK lengths of K dimension of local matrix [M] +!> @param[in] full global "shared" vector [full] +!> @param[out] local "private" block vector [local] +!> @param[in] lxyz_block number of blocks +!> @param[in] xyz_block block dimensions + SUBROUTINE lcopy_ilu(ni,nj,nk,full,local,lxyz_block,xyz_block) +! use mod_genrl + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k + INTEGER ni,nj,nk,i1, j1, k1, i2, j2, k2, i_max, j_max, k_max, ii + DOUBLE PRECISION full(ni,nj,nk) + DOUBLE PRECISION local(block_i,block_j,block_k,*) + INTEGER lxyz_block, xyz_block(3,lxyz_block) + +! search all blocks - identify private + DO ii = 1, lxyz_block + i = xyz_block(1,ii) + j = xyz_block(2,ii) + k = xyz_block(3,ii) +! global block offset (-1) + i2 = block_i*(i-1) + j2 = block_j*(j-1) + k2 = block_k*(k-1) +! block length + k_max = min(block_k,nk-k2) + j_max = min(block_j,nj-j2) + i_max = min(block_i,ni-i2) +! clear all (dummy-)values + DO k1 = k_max + 1, block_k + DO j1 = 1, block_j + DO i1 = 1, block_i +! | + + | | * + | +! | # # | | # # | + local(i1,j1,k1,ii) = 0.0D0 + END DO + END DO + END DO + DO k1 = 1, k_max + DO j1 = j_max + 1, block_j + DO i1 = 1, block_i +! | + # | | * # | +! | # # | | # # | + local(i1,j1,k1,ii) = 0.0D0 + END DO + END DO + END DO + DO k1 = 1, k_max + DO j1 = 1, j_max + DO i1 = i_max + 1, block_i +! | # # | | * # | +! | # # | | # # | + local(i1,j1,k1,ii) = 0.0D0 + END DO + END DO + END DO +! copy private blocks in "local" + DO k1 = 1, k_max + DO j1 = 1, j_max + DO i1 = 1, i_max + local(i1,j1,k1,ii) = full(i2+i1,j2+j1,k2+k1) + END DO + END DO + END DO + END DO +! + RETURN + END + +!> @brief copy "shared", collect the [local] "private" blocks into the "shared" [full] vector +!> @param[in] NI lengths of I dimension of local matrix [M] +!> @param[in] NJ lengths of J dimension of local matrix [M] +!> @param[in] NK lengths of K dimension of local matrix [M] +!> @param[out] full global "shared" vector [full] +!> @param[in] local "private" block vector [local] +!> @param[in] lxyz_block number of blocks +!> @param[in] xyz_block block dimensions + SUBROUTINE lcopy_bak_ilu(ni,nj,nk,full,local,lxyz_block,xyz_block) +! use mod_genrl + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k + INTEGER ni,nj,nk,i1, j1, k1, i2, j2, k2, i_max, j_max, k_max, ii + DOUBLE PRECISION full(ni,nj,nk) + DOUBLE PRECISION local(block_i,block_j,block_k,*) + INTEGER lxyz_block, xyz_block(3,lxyz_block) + +! search all blocks - identify private + DO ii = 1, lxyz_block + i = xyz_block(1,ii) + j = xyz_block(2,ii) + k = xyz_block(3,ii) +! global block offset (-1) + i2 = block_i*(i-1) + j2 = block_j*(j-1) + k2 = block_k*(k-1) +! block length + k_max = min(block_k,nk-k2) + j_max = min(block_j,nj-j2) + i_max = min(block_i,ni-i2) +! copy bak private blocks in "full" + DO k1 = 1, k_max + DO j1 = 1, j_max + DO i1 = 1, i_max + full(i2+i1,j2+j1,k2+k1) = local(i1,j1,k1,ii) + END DO + END DO + END DO + END DO +!$OMP barrier +! + RETURN + END + +!> @brief copy surface/boundary (position-1) - make private +!> @param[in] NI lengths of I dimension of local matrix [M] +!> @param[in] NJ lengths of J dimension of local matrix [M] +!> @param[in] NK lengths of K dimension of local matrix [M] +!> @param[in] ii block index number +!> @param[in] full global "shared" vector +!> @param[out] local "private" boundary buffer +!> @param[in] lxyz_block number of blocks +!> @param[in] xyz_block block dimensions + SUBROUTINE lsurf_ilu(ni,nj,nk,ii,full,local,lxyz_block,xyz_block) +! use mod_genrl + use mod_blocking_size + IMPLICIT NONE + integer :: i, j, k + INTEGER lxyz_block, xyz_block(3,lxyz_block) + INTEGER ni,nj,nk,i1, j1, k1, i2, j2, k2, i_max, j_max, k_max, ii, offs + DOUBLE PRECISION full(ni,nj,nk) + DOUBLE PRECISION local(block_i*block_j+block_i*block_k+ & + block_j*block_k) + +! search all blocks - identify private + i = xyz_block(1,ii) + j = xyz_block(2,ii) + k = xyz_block(3,ii) +! global block offset (-1) + i2 = block_i*(i-1) + j2 = block_j*(j-1) + k2 = block_k*(k-1) +! block length + i_max = min(block_i,ni-i2) + j_max = min(block_j,nj-j2) + k_max = min(block_k,nk-k2) + +! I-dim + offs = 0 + IF (i2>=1) THEN + DO k1 = 1, k_max + DO j1 = 1, j_max + local(offs+j1+block_j*(k1-1)) = full(i2,j2+j1,k2+k1) + END DO + END DO + ELSE + DO k1 = 1, k_max + DO j1 = 1, j_max + local(offs+j1+block_j*(k1-1)) = 0.0D0 + END DO + END DO + END IF +! J-dim + offs = offs + block_j*block_k + IF (j2>=1) THEN + DO k1 = 1, k_max + DO i1 = 1, i_max + local(offs+i1+block_i*(k1-1)) = full(i2+i1,j2,k2+k1) + END DO + END DO + ELSE + DO k1 = 1, k_max + DO i1 = 1, i_max + local(offs+i1+block_i*(k1-1)) = 0.0D0 + END DO + END DO + END IF +! K-dim + offs = offs + block_i*block_k + IF (k2>=1) THEN + DO j1 = 1, j_max + DO i1 = 1, i_max + local(offs+i1+block_i*(j1-1)) = full(i2+i1,j2+j1,k2) + END DO + END DO + ELSE + DO j1 = 1, j_max + DO i1 = 1, i_max + local(offs+i1+block_i*(j1-1)) = 0.0D0 + END DO + END DO + END IF +! + RETURN + END diff --git a/solve/qddot.f90 b/solve/qddot.f90 new file mode 100644 index 0000000..3d65e8a --- /dev/null +++ b/solve/qddot.f90 @@ -0,0 +1,130 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief quad precision; to accumulate two vectors +!> @param[in] n vector length +!> @param[in] dx first vector [dx] +!> @param[in] incx step size for [dx] +!> @param[in] dy second vector [dy] +!> @param[in] incy step size for [dy] +!> @return dot product of [dx].[dy] +!> @details +!> This is a modification for quad precision accumulation !!!\n +!> qd: quad precision; d: to accumulate\n +!> - dt = qd(1) +d\n +!> - qd(2) = qd(2) +(d -(dt -qd(1)))\n +!> - qd(1) = dt\n +!> +!> New: enhanced numeric stability with an overlap driven by "wrong"\n +!> +!> forms the dot product of two vectors.\n +!> uses unrolled loops for increments equal to one.\n +!> jack dongarra, linpack, 3/11/78.\n +!> modified 12/3/93, array(1) declarations changed to array(*)\n + DOUBLE PRECISION FUNCTION qddot(n,dx,incx,dy,incy) + DOUBLE PRECISION dx(n), dy(n), d, dquad(2) + DOUBLE PRECISION dtemp + DOUBLE PRECISION da(4), dquada(4,2) + DOUBLE PRECISION dtempa(4) + DOUBLE PRECISION, PARAMETER :: wrong=1.00000000000001d0 + INTEGER i, incx, incy, ix, iy, m, mp1, n + + qddot = 0.0D0 + dquad(1) = 0.0D0 + dquad(2) = 0.0D0 + + IF (n<=0) RETURN + IF (incx==1 .AND. incy==1) GO TO 20 + +! Code for unequal inCrements or equal inCrements +! not equal to 1 + + ix = 1 + iy = 1 + IF (incx<0) ix = (-n+1)*incx + 1 + IF (incy<0) iy = (-n+1)*incy + 1 + DO i = 1, n + d = dx(ix)*dy(iy) + dtemp = (dquad(1) + d)*wrong + dquad(2) = dquad(2) + (d-(dtemp-dquad(1))) + dquad(1) = dtemp + ix = ix + incx + iy = iy + incy + END DO + qddot = dquad(2) + dquad(1) + RETURN + +! Code for both inCrements equal to 1 + +! Clean-up loop + +20 m = mod(n,4) + DO i = 1, 4 + dquada(i,1) = 0.0D0 + dquada(i,2) = 0.0D0 + END DO + + IF (m==0) GO TO 40 + DO i = 1, m + d = dx(i)*dy(i) + dtemp = (dquad(1) + d)*wrong + dquad(2) = dquad(2) + (d-(dtemp-dquad(1))) + dquad(1) = dtemp + END DO + IF (n<4) GO TO 60 +40 mp1 = m + 1 + + DO i = mp1, n, 4 + da(1) = dx(i)*dy(i) + da(2) = dx(i+1)*dy(i+1) + da(3) = dx(i+2)*dy(i+2) + da(4) = dx(i+3)*dy(i+3) + dtempa(1) = (dquada(1,1) + da(1))*wrong + dtempa(2) = (dquada(2,1) + da(2))*wrong + dtempa(3) = (dquada(3,1) + da(3))*wrong + dtempa(4) = (dquada(4,1) + da(4))*wrong + dquada(1,2) = dquada(1,2) + (da(1)-(dtempa(1)-dquada(1,1))) + dquada(2,2) = dquada(2,2) + (da(2)-(dtempa(2)-dquada(2,1))) + dquada(3,2) = dquada(3,2) + (da(3)-(dtempa(3)-dquada(3,1))) + dquada(4,2) = dquada(4,2) + (da(4)-(dtempa(4)-dquada(4,1))) + dquada(1,1) = dtempa(1) + dquada(2,1) = dtempa(2) + dquada(3,1) = dtempa(3) + dquada(4,1) = dtempa(4) + END DO +60 CONTINUE + DO i = 1, 4 + d = dquada(i,2) + dtemp = (dquad(1) + d)*wrong + dquad(2) = dquad(2) + (d-(dtemp-dquad(1))) + dquad(1) = dtemp + END DO + DO i = 1, 4 + d = dquada(i,1) + dtemp = (dquad(1) + d)*wrong + dquad(2) = dquad(2) + (d-(dtemp-dquad(1))) + dquad(1) = dtemp + END DO + qddot = dquad(2) + dquad(1) + + RETURN + END diff --git a/solve/reduction.f90 b/solve/reduction.f90 new file mode 100644 index 0000000..fa78799 --- /dev/null +++ b/solve/reduction.f90 @@ -0,0 +1,87 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief OpenMP reduction (sum) routine, (enhanced precision) +!> @param[in] s_private "private" values from each thread +!> @param[out] sh_help temporary "shared" helper array +!> @param[in] m vector size (number of reductions) +!> @param[out] S result, global sum (OpenMP private) +!> @details +!> New: enhanced numeric stability with an overlap driven by "wrong"\n +!> +!> build the sum (reduction) from s_private to S, where S are overwritten\n +!> and not used to compute the sum\n + SUBROUTINE xsum_0(m,s_private,s,sh_help) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' +! precision staff + DOUBLE PRECISION dquad(2) + DOUBLE PRECISION, PARAMETER :: wrong=1.00000000000001d0 +! number of threads + INTEGER t, tt +! loop variables + INTEGER i, k, l, m +! sh_help(#thread * m) : shared array to compute temp. values + DOUBLE PRECISION s(m), s_private(m), sh_help(*) + +! + t = omp_get_num_of_threads() + tt = omp_get_his_thread_num() + 1 +! store values of all "m" reductions + sh_help(tt) = s_private(1) + DO l = 2, m + sh_help(tt+(l-1)*t) = s_private(l) + END DO +!$OMP barrier +! +!$OMP do schedule(static) + DO l = 1, m +! i: offset for each reduction + i = (l-1)*t +!org s_private(l) = sh_help(1+i) +!org DO k = 2, t +!org s_private(l) = s_private(l) + sh_help(k+i) +!org END DO +!org sh_help(1+i) = s_private(l) +! +! enhanced precision + dquad(1) = sh_help(1+i) + dquad(2) = 0.0D0 + DO k = 2, t + s_private(l) = (dquad(1) + sh_help(k+i))*wrong + dquad(2) = dquad(2) + (sh_help(k+i)-(s_private(l)-dquad(1))) + dquad(1) = s_private(l) + END DO + sh_help(1+i) = dquad(2) + dquad(1) + END DO +!$OMP end do nowait +!$OMP barrier +! +! copy private + DO l = 1, m + i = (l-1)*t + s(l) = sh_help(1+i) + END DO +! + RETURN + END diff --git a/solve/set_dval.f90 b/solve/set_dval.f90 new file mode 100644 index 0000000..b2310bc --- /dev/null +++ b/solve/set_dval.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialise a double precision vector +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE set_dval(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector +! i : loop variable + integer :: n, i +! vector [x] + double precision, dimension (n) :: x + double precision :: alpha + + DO i = 1, n + x(i) = alpha + END DO + RETURN + END + +!> @brief initialise a double precision vector, (OpenMP version) +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE omp_set_dval(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector +! i : loop variable + integer :: n, i, tpos, tanz +! vector [x] + double precision, dimension (n) :: x + double precision :: alpha + + CALL omp_part(n,tpos,tanz) + DO i = tpos, tpos + tanz - 1 + x(i) = alpha + END DO + RETURN + END diff --git a/solve/set_ival.f90 b/solve/set_ival.f90 new file mode 100644 index 0000000..ca6205e --- /dev/null +++ b/solve/set_ival.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialise an integer vector +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE set_ival(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector +! i : loop variable + integer :: n, i +! vector [x] + integer, dimension (n) :: x + integer :: alpha + + DO i = 1, n + x(i) = alpha + END DO + RETURN + END + +!> @brief initialise an integer vector, (OpenMP version) +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE omp_set_ival(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector +! i : loop variable + integer :: n, i, tpos, tanz +! vector [x] + integer, dimension (n) :: x + integer :: alpha + + CALL omp_part(n,tpos,tanz) + DO i = tpos, tpos + tanz - 1 + x(i) = alpha + END DO + RETURN + END diff --git a/solve/set_lval.f90 b/solve/set_lval.f90 new file mode 100644 index 0000000..436a2a4 --- /dev/null +++ b/solve/set_lval.f90 @@ -0,0 +1,60 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialise a logical vector +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE set_lval(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector + INTEGER n +! vector [x] + LOGICAL x(n), alpha +! i : loop variable + INTEGER i + + DO i = 1, n + x(i) = alpha + END DO + RETURN + END + +!> @brief initialise a logical vector, (OpenMP version) +!> @param[in] N length of [x]-vectors +!> @param[in] alpha value for initialisation +!> @param[out] x initialised vector [x] + SUBROUTINE omp_set_lval(n,alpha,x) + IMPLICIT NONE +! N : length of [x]-vector + INTEGER n +! vector [x] + LOGICAL x(n), alpha +! i : loop variable + INTEGER i, tpos, tanz + + CALL omp_part(n,tpos,tanz) + DO i = tpos, tpos + tanz - 1 + x(i) = alpha + END DO + RETURN + END diff --git a/solve/solve.f90 b/solve/solve.f90 new file mode 100644 index 0000000..9ea1c15 --- /dev/null +++ b/solve/solve.f90 @@ -0,0 +1,181 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief main routine to solve a linear equation system, calls "solve_type" (wrapper) +!> @param[in] icode specify the physical value +!> @param[in] species transport species index +!> @param[in,out] x_solution solution vector of the solved linear system, may be also the start input +!> @param[in] errorc error +!> @param[in] apar setup explicit or implicit solver (disabled), default 1.0 +!> @param[in] ctrl solver code +!> @param[in] ismpl local sample index +!> @details +!> solve system equations by preconditioned krylov solvers (bicgstab) or SIP (NAG) and others\n + SUBROUTINE solve(icode,species,x_solution,errorc,apar,ctrl,ismpl) + use arrays + use mod_genrl + use mod_flow + use mod_temp + use mod_conc + use mod_linfos + IMPLICIT NONE + integer :: ismpl + double precision :: apar, errorc + ! double precision :: dnormalise + integer :: icode + ! integer :: itst + integer :: mxit + integer :: species + integer :: mfactor + integer :: ctrl, criteria, precondition, solvername + double precision :: x_solution(i0*j0*k0) +! only for tests with 'abbruch' + double precision :: moderrorc + ! double precision :: enough +#ifdef BENCH + double precision :: trun + double precision :: tend +#endif + intrinsic dsqrt, dble, abs + +! ------------- + moderrorc = errorc + IF (ctrl<0) THEN + WRITE(*,*) & + 'error: old solver compatibility no longer supported' + STOP + END IF + +! ************************************************************************** +! solvername = +! *0 : BiCGStab [:parallel] +! 1 : not supported, formerly: NAG [:serial] +! 2 : CG [:parallel] ( prove symmetry, if not then BiCGStab ) +! 3 : PLU [:serial] (LAPACK) and math tests (stability) +! (4-7 : not in use !) +! criteria = < switch to set when should break > +! 0 : relative stopping crit. : ||[res]|| < depsilon*||[res0]|| +! 1 : absolute stopping crit. : ||[res]|| < depsilon +! 2 : maximum stopping crit. : max(abs([res])) < depsilon +! 3 : abs. and rel. stopping crit. : ( ||[res]|| < depsilon ) and ( ||[res]|| < 0.99d0*||[res0]|| ) +! 0.99d0 is a constant for testing only, it is named 'minRel' in 'abbruch.f' +! *4 : like '3', but with auto detected range for depsilon, default depsilon used when detection fails +! (5-7 : not in use !) +! precondition = +! *0 : ILU [:parallel] +! 1 : SSOR [:serial] +! 2 : Diagonal [:parallel] +! 3 : None [:] +! (4-7 : not in use !) +! * : recommended (ctrl = 64) +! and (ctrl = 67) : for testing +! +! [ ctrl = solvername + 16*criteria + 256*precondition ] +! extract [ ctrl ] : +! solvername = mod(ctrl,16) +! ctrl = ctrl/16 +! criteria = mod(ctrl,16) +! ctrl = ctrl/16 +! precondition = ctrl +! + CALL decntrl3(ctrl,solvername,criteria,precondition) + +! ************************************************************************** + +! ------------- +! defualt multiply factoor + mfactor = 1 +! + IF (abs(icode)==pv_pres) THEN + mxit = lmaxitf + IF (criteria>=4) THEN + criteria = 1 + moderrorc = nltolf*1.0D-2 + END IF + END IF + + IF (abs(icode)==pv_conc) THEN + mxit = lmaxitc + IF (criteria>=4) THEN + criteria = 1 + moderrorc = nltolc*1.0D-2 + END IF + END IF + + IF (abs(icode)==pv_temp) THEN + mxit = lmaxitt + IF (criteria>=4) THEN + criteria = 1 + moderrorc = nltolt*1.0D-2 + END IF + END IF + + IF (abs(icode)==pv_head) THEN + mxit = lmaxitf + IF (criteria>=4) THEN + criteria = 1 + moderrorc = nltolf*1.0D-2 + END IF + END IF + +! ------------- + +! ------------- + IF (tec_out) THEN +! save current state of the right side vector - may be modified after "solve_type" + CALL dcopy(i0*j0*k0,w(1,1,1,ismpl),1,lss_tmp(1,ismpl),1) + END IF + +! ################################################################## +! # solver # +! ################################################################## + +#ifdef BENCH + CALL sys_cputime(trun) +#endif + CALL solve_type(i0,j0,k0*mfactor,x_solution,w(1,1,1,ismpl),moderrorc, & + bc_mask(1,ismpl),solvername,precondition,mxit,criteria, & + a(1,1,1,ismpl),b(1,1,1,ismpl),c(1,1,1,ismpl),d(1,1,1,ismpl), & + e(1,1,1,ismpl),f(1,1,1,ismpl),g(1,1,1,ismpl),r,apar, & + ud(1,1,1,ismpl),ismpl) +#ifdef BENCH + CALL sys_cputime(tend) + WRITE(*,*) ' linear system solver time:', tend - trun, 'sec' +#endif + +! ################################################################## + +! ------------- +! "icode" < 0 indicates a default input/output in the [x] vector + IF (icode<0) THEN + CALL dcopy(i0*j0*k0,x_solution,1,x(1,1,1,ismpl),1) + END IF + +! ------------- + IF (tec_out) THEN +! restore the state of the right side vector + CALL dcopy(i0*j0*k0,lss_tmp(1,ismpl),1,w(1,1,1,ismpl),1) + END IF + + + RETURN + END diff --git a/solve/solve_debug.f90 b/solve/solve_debug.f90 new file mode 100644 index 0000000..8ff0046 --- /dev/null +++ b/solve/solve_debug.f90 @@ -0,0 +1,124 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief output routine to debug "solve.f90" input, use this instead of "call solve(...)" +!> @param[in] csf suffix for the output file name +!> @param[in] x_cur current solution vector [x] +!> @param[in] ismpl local sample index + SUBROUTINE solve_debug(csf,x_cur,ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k, l +! residuum + DOUBLE PRECISION, ALLOCATABLE :: dresid(:) +! max. normalisation value + DOUBLE PRECISION, ALLOCATABLE :: dmaxnrm(:) + DOUBLE PRECISION x_cur(i0,j0,k0,1) + ! DOUBLE PRECISION dvor + ! CHARACTER cnach + character (len=*) :: csf + LOGICAL test_null + EXTERNAL test_null + INTRINSIC max, abs + +! compute "residuum" + ALLOCATE(dresid(i0*j0*k0)) + ALLOCATE(dmaxnrm(i0*j0*k0)) + CALL s_mvp(i0,j0,k0,x_cur(1,1,1,ismpl),dresid,a(1,1,1,ismpl), & + b(1,1,1,ismpl),c(1,1,1,ismpl),d(1,1,1,ismpl),e(1,1,1,ismpl), & + f(1,1,1,ismpl),g(1,1,1,ismpl)) + CALL daxpy(i0*j0*k0,-1.D0,w(1,1,1,ismpl),1,dresid,1) + + l = 0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + l = l + 1 +! dmaxnrm(l) = abs(w(i,j,k,ismpl)) +!debug cnach = 'w' +!debug dvor = dmaxnrm(l) +! if (K0.gt.1.and.k.gt.1) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(a(i,j,k,ismpl) *x_Cur(i,j,k-1,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'a' +!debug dvor = dmaxnrm(l) +! if (J0.gt.1.and.j.gt.1) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(b(i,j,k,ismpl) *x_Cur(i,j-1,k,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'b' +!debug dvor = dmaxnrm(l) +! if (I0.gt.1.and.i.gt.1) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(C(i,j,k,ismpl) *x_Cur(i-1,j,k,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'c' +!debug dvor = dmaxnrm(l) +! dmaxnrm(l) = max(dmaxnrm(l), +! & abs(d(i,j,k,ismpl) *x_Cur(i,j,k,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'd' +!debug dvor = dmaxnrm(l) +! if (I0.gt.1.and.i.lt.I0) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(e(i,j,k,ismpl) *x_Cur(i+1,j,k,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'e' +!debug dvor = dmaxnrm(l) +! if (J0.gt.1.and.j.lt.J0) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(f(i,j,k,ismpl) *x_Cur(i,j+1,k,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'f' +!debug dvor = dmaxnrm(l) +! if (K0.gt.1.and.k.lt.K0) dmaxnrm(l) = max(dmaxnrm(l), +! & abs(g(i,j,k,ismpl) *x_Cur(i,j,k+1,ismpl))) +!debug if (dvor.ne.dmaxnrm(l) ) cnach = 'g' +!debug if (cnach.ne.'d'.and.cnach.ne.'w') +!debug & write(*,*) ' ['//cnach//']',l + IF (bc_mask(l,ismpl)=='+') THEN +! diagonal dominance + dmaxnrm(l) = abs(d(i,j,k,ismpl)) + IF ( .NOT. test_null(x_cur(i,j,k, & + ismpl))) dmaxnrm(l) = abs(d(i,j,k,ismpl)* & + x_cur(i,j,k,ismpl)) + ELSE + dmaxnrm(l) = 1.D0 + END IF + END DO + END DO + END DO + + OPEN(999,file='system_'//csf//'.dat',status='REPLACE') + WRITE(999,*) '% w x res err base | a b c d e f g' + l = 0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + l = l + 1 + WRITE(999,'(5d20.8,2A,7d20.8)') w(i,j,k,ismpl), & + x_cur(i,j,k,ismpl), dresid(l), dresid(l)/dmaxnrm(l), & + dmaxnrm(l), ' ' // bc_mask(l,ismpl), ' | ', & + a(i,j,k,ismpl), b(i,j,k,ismpl), c(i,j,k,ismpl), & + d(i,j,k,ismpl), e(i,j,k,ismpl), f(i,j,k,ismpl), & + g(i,j,k,ismpl) + END DO + END DO + END DO + WRITE(999,*) '% w x res err base | a b c d e f g' + CLOSE(999) + DEALLOCATE(dmaxnrm) + DEALLOCATE(dresid) + RETURN + END diff --git a/solve/solve_type.f90 b/solve/solve_type.f90 new file mode 100644 index 0000000..3ddf3b7 --- /dev/null +++ b/solve/solve_type.f90 @@ -0,0 +1,231 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief wrapper routine to call each kind of linear system solver +!> @param[in] ni lengths of I dimension of local matrix [M] +!> @param[in] nj lengths of J dimension of local matrix [M] +!> @param[in] nk lengths of K dimension of local matrix [M] +!> @param[in,out] l_x solution vector [x], on start = start vector +!> @param[in] l_w right side, vector [b] +!> @param[in] moderrc_ only for tests with 'abbruch' +!> @param[in] l_bc_mask boundary condition pattern (mask) +!> @param[in] solvername solver name, code for CG, BiCGStab... +!> @param[in] precondition preconditioner code for None, Diagonal, SSOR or ILU(0) +!> @param[in] MXIT max iteration number +!> @param[in] criteria_ precision criteria mode to break iterations\n +!> - 0 : relative stopping crit.: ||[res]|| < depsilon*||[res0]||\n +!> - 1 : absolute stopping crit.: ||[res]|| < depsilon\n +!> - 2 : maximum stopping crit.: max(abs([res])) < depsilon\n +!> first [res]^=[r], later (if precise enough): [res]^=([M]x[x]-[b]) +!> @param[in] L_A 1. diagonal of the system matrix [M] +!> @param[in] L_B 2. diagonal of the system matrix [M] +!> @param[in] L_C 3. diagonal of the system matrix [M] +!> @param[in] L_D 4. diagonal of the system matrix [M] +!> @param[in] L_E 5. diagonal of the system matrix [M] +!> @param[in] L_F 6. diagonal of the system matrix [M] +!> @param[in] L_G 7. diagonal of the system matrix [M] +!> @param[in] l_r random vector [r0_hat] ^= [r0^] +!> @param[in] APAR explicit - implicit solver switch (default 1.0) +!> @param[in] L_UD helper diagonal elements for preconditioning +!> @param[in] ismpl local sample index +!> @details +!> Function: wrapper for any solver, spec. by criteria\n +!> Input/Output: see in 'solver.f90'\n + SUBROUTINE solve_type(ni,nj,nk,l_x,l_w,moderrc_,l_bc_mask, & + solvername,precondition,mxit,criteria_,l_a,l_b,l_c,l_d,l_e, & + l_f,l_g,l_r,apar,l_ud,ismpl) + use arrays + use mod_linfos + use mod_genrl + IMPLICIT NONE + INTEGER ni, nj, nk + DOUBLE PRECISION moderrc_, l_a(ni,nj,nk), l_b(ni,nj,nk), & + l_c(ni,nj,nk), l_d(ni,nj,nk), l_e(ni,nj,nk), l_f(ni,nj,nk), & + l_g(ni,nj,nk), l_ud(ni,nj,nk) + DOUBLE PRECISION apar, l_x(ni,nj,nk), l_w(ni,nj,nk), & + l_r(ni,nj,nk) + CHARACTER l_bc_mask(ni,nj,nk) + INTEGER criteria_, solvername, mxit, ii + INTEGER precondition, ismpl + LOGICAL test_symmetry, ldummy + EXTERNAL test_symmetry + + +! ################################################################## +! # solver # +! ################################################################## + +! ** nag solver not supported anymore ** + IF (solvername==1) THEN + write(unit = *, fmt = *) '[E] error: nag solver not& + & supported anymore.' + stop + END IF + +! --------------------------------------------------------- + +! ** use Cg solver ** + IF (solvername==2) THEN +! test about symmetry + IF (test_symmetry(ismpl)) THEN +! symmetriC solver ilu-preCo + IF (precondition==0) THEN + IF (linfos(4)>=2) WRITE(*,*) ' ilu precondition' + CALL omp_sym_solve_ilu(ni,nj,nk,l_x,l_w,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + l_ud,lss_bound_block(1,1,1,1,1,ismpl), & + lss_dnrm(1,ismpl),lss_lma(1,1,ismpl), & + lss_lmb(1,1,ismpl),lss_lmc(1,1,ismpl), & + lss_lmd(1,1,ismpl),lss_lme(1,1,ismpl), & + lss_lmf(1,1,ismpl),lss_lmg(1,1,ismpl), & + lss_lud(1,1,ismpl),lss_lx(1,1,ismpl), & + lss_lb(1,1,ismpl),lss_ldnrm(1,1,ismpl), & + lss_lloctmp(1,1,1,ismpl),lss_ud_block(1,1,1,ismpl), & + ismpl) + RETURN + END IF + + IF (precondition==1) THEN + IF (linfos(4)>=2) WRITE(*,*) ' ssor precondition' + CALL omp_sym_solve_ssor(ni,nj,nk,l_x,l_w,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + + IF (precondition==2) THEN + IF (linfos(4)>=2) WRITE(*,*) ' diagonal precondition' + CALL omp_sym_solve_diag(ni,nj,nk,l_x,l_w,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + + IF (precondition==3) THEN + IF (linfos(4)>=2) WRITE(*,*) ' no precondition' + CALL omp_sym_solve(ni,nj,nk,l_x,l_w,moderrc_,l_bc_mask, & + mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + ELSE + solvername = 0 + END IF + END IF + +! --------------------------------------------------------- + +! ** use biCgstab solver ** + IF (solvername==0) THEN +! generic solver ilu-preco + IF (precondition==0) THEN + IF (linfos(4)>=2) WRITE(*,*) ' ilu precondition' + CALL omp_gen_solve_ilu(ni,nj,nk,l_x,l_w,l_r,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + l_ud,lss_bound_block(1,1,1,1,1,ismpl),lss_dnrm(1,ismpl), & + lss_lma(1,1,ismpl),lss_lmb(1,1,ismpl), & + lss_lmc(1,1,ismpl),lss_lmd(1,1,ismpl), & + lss_lme(1,1,ismpl),lss_lmf(1,1,ismpl), & + lss_lmg(1,1,ismpl),lss_lud(1,1,ismpl),lss_lx(1,1,ismpl), & + lss_lb(1,1,ismpl),lss_lr0_hat(1,1,ismpl), & + lss_ldnrm(1,1,ismpl),lss_lloctmp(1,1,1,ismpl), & + lss_ud_block(1,1,1,ismpl),ismpl) + RETURN + END IF + + IF (precondition==1) THEN + IF (linfos(4)>=2) WRITE(*,*) ' ssor precondition' + CALL omp_gen_solve_ssor(ni,nj,nk,l_x,l_w,l_r,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + + IF (precondition==2) THEN + IF (linfos(4)>=2) WRITE(*,*) ' diagonal precondition' + CALL omp_gen_solve_diag(ni,nj,nk,l_x,l_w,l_r,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + + IF (precondition==3) THEN + IF (linfos(4)>=2) WRITE(*,*) ' no precondition' + CALL omp_gen_solve(ni,nj,nk,l_x,l_w,l_r,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + lss_lloctmp(1,1,1,ismpl),lss_dnrm(1,ismpl),ismpl) + RETURN + END IF + END IF + +! --------------------------------------------------------- + +! ** use PLU (LAPACK) and make math tests ** + IF (solvername==3) THEN +! -------------------------------- +! test about symmetry and stability + ldummy = test_symmetry(ismpl) + + CALL test_matrix(ismpl) +! -------------------------------- +! memory space enough ? + ii = ni*nj + IF (ni==1) ii = ni*nj + IF (nj==1) ii = ni*nj + IF (nk==1) ii = ni + + IF (8.0D0*dble(3*ii+1)*dble(ni*nj*nk)<=2.0D9) THEN + CALL direct_solve(ni,nj,nk,l_x,l_w,l_a,l_b,l_c,l_d,l_e, & + l_f,l_g) + ELSE + IF (linfos(4)>=2) WRITE(*,'(A,F12.2,A)') & + ' choose BICGStab (PLU need :', & + (8.0D0*dble(3*ii+1)*dble(ni*nj*nk)/(1024.0D0*1024.0D0)), & + ' MByte, which is more than 2GByte)' +! BiCGStab with ILU(0) precondition + CALL omp_gen_solve_ilu(ni,nj,nk,l_x,l_w,l_r,moderrc_, & + l_bc_mask,mxit,criteria_,l_a,l_b,l_c,l_d,l_e,l_f,l_g, & + l_ud,lss_bound_block(1,1,1,1,1,ismpl),lss_dnrm(1,ismpl), & + lss_lma(1,1,ismpl),lss_lmb(1,1,ismpl), & + lss_lmc(1,1,ismpl),lss_lmd(1,1,ismpl), & + lss_lme(1,1,ismpl),lss_lmf(1,1,ismpl), & + lss_lmg(1,1,ismpl),lss_lud(1,1,ismpl),lss_lx(1,1,ismpl), & + lss_lb(1,1,ismpl),lss_lr0_hat(1,1,ismpl), & + lss_ldnrm(1,1,ismpl),lss_lloctmp(1,1,1,ismpl), & + lss_ud_block(1,1,1,ismpl),ismpl) + END IF + END IF + +! --------------------------------------------------------- + +! multi-phase newton bicgstb solver ilu-preco + IF (solvername==4) THEN + write(unit = *, fmt = *) '[E] error: multi-phase newton solver not'// & + 'supported anymore.' + stop + END IF + + +! --------------------------------------------------------- + + RETURN + END diff --git a/solve/ssor_mvp_single.f90 b/solve/ssor_mvp_single.f90 new file mode 100644 index 0000000..a25435a --- /dev/null +++ b/solve/ssor_mvp_single.f90 @@ -0,0 +1,154 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief apply 7point-star matrix multiply [as]:=[M]x[s] +!> @param[in] N_I lengths of I dimension of local matrix [M] +!> @param[in] N_J lengths of J dimension of local matrix [M] +!> @param[in] N_K lengths of K dimension of local matrix [M] +!> @param[in] s vector [s] +!> @param[out] as vector [as] +!> @param[out] t temporary vector, used for computation +!> @param[in] MA 1. diagonal of the system matrix [M] +!> @param[in] MB 2. diagonal of the system matrix [M] +!> @param[in] MC 3. diagonal of the system matrix [M] +!> @param[in] MD 4. (main) diagonal of the system matrix [M] +!> @param[in] ME 5. diagonal of the system matrix [M] +!> @param[in] MF 6. diagonal of the system matrix [M] +!> @param[in] MG 7. diagonal of the system matrix [M] +!> @details +!> OpenMP parallelised, general version - no special blocking\n +!> apply 7point-star matrix multiply\n +!> compute [as]:=[M]x[s], [s],[as],[M] given in 3-D-structure\n +!> Data-Cube :\n +!> @image html cube.png +! k * * * * +! / * * * +! 0 -j * * * * * +! | * * * +! i * * * +! * * * * + SUBROUTINE ssor_mvp_single(n_i,n_j,n_k,s,as,t,ma,mb,mc,md,me,mf, & + mg) + use mod_OMP_TOOLS + IMPLICIT NONE + INCLUDE 'OMP_TOOLS.inc' + INTEGER n_i, n_j, n_k +! + DOUBLE PRECISION s(n_i,n_j,n_k), as(n_i,n_j,n_k) + DOUBLE PRECISION ma(n_i,n_j,n_k), mb(n_i,n_j,n_k), & + mc(n_i,n_j,n_k) + DOUBLE PRECISION md(n_i,n_j,n_k), me(n_i,n_j,n_k), & + mf(n_i,n_j,n_k) + DOUBLE PRECISION mg(n_i,n_j,n_k) +! t : tmp. vector + DOUBLE PRECISION t(n_i,n_j,n_k) +! loop variable + INTEGER i, j, k +! + INTEGER panz, ppos + EXTERNAL panz, ppos +! THREAD-stuff + ! INTEGER tpos, tanz +! + INTEGER ijk + + +! compute boundary size + ijk = n_i*n_j*n_k + + +! ##################################################################### +! Main +! given : A=L+D+U + +! t:=(D+U)^(-1)*s + +!$OMP master + CALL dcopy(ijk,s,1,t,1) + + + DO k = n_k, 1, -1 + DO j = n_j, 1, -1 + DO i = n_i, 1, -1 + IF (i<n_i) t(i,j,k) = t(i,j,k) - me(i,j,k)*t(i+1,j,k) + IF (j<n_j) t(i,j,k) = t(i,j,k) - mf(i,j,k)*t(i,j+1,k) + IF (k<n_k) t(i,j,k) = t(i,j,k) - mg(i,j,k)*t(i,j,k+1) +!AW ugly hack ... + IF (md(i,j,k)/=0.0D0) THEN + t(i,j,k) = t(i,j,k)/md(i,j,k) + END IF + END DO + END DO + END DO + + + +!CC t2 : tot, t3 = as +! t2 =(s - D*t) +! t3 =(D+L)^(-1) * t2 + + CALL dcopy(ijk,s,1,as,1) + +!AW call daxpy(ijk,-1.0d0,t,1,as,1) + DO k = 1, n_k + DO j = 1, n_j + DO i = 1, n_i + as(i,j,k) = as(i,j,k) - t(i,j,k)*md(i,j,k) + END DO + END DO + END DO + + + DO k = 1, n_k + DO j = 1, n_j + DO i = 1, n_i + IF (i>1) as(i,j,k) = as(i,j,k) - mc(i,j,k)*as(i-1,j,k) + IF (j>1) as(i,j,k) = as(i,j,k) - mb(i,j,k)*as(i,j-1,k) + IF (k>1) as(i,j,k) = as(i,j,k) - ma(i,j,k)*as(i,j,k-1) +!AW ugly hack ... + IF (md(i,j,k)/=0.0D0) THEN + as(i,j,k) = as(i,j,k)/md(i,j,k) + END IF + END DO + END DO + END DO + + +!CC t3 = as, t4 : tot +! t4 = t + t3 +! A^T*s = D * t4 + + CALL daxpy(ijk,1.0D0,t,1,as,1) + + DO k = 1, n_k + DO j = 1, n_j + DO i = 1, n_i + as(i,j,k) = as(i,j,k)*md(i,j,k) + END DO + END DO + END DO +!$OMP end master +!$OMP barrier + + + RETURN + END diff --git a/solve/test_matrix.f90 b/solve/test_matrix.f90 new file mode 100644 index 0000000..bf2f766 --- /dev/null +++ b/solve/test_matrix.f90 @@ -0,0 +1,152 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief test the numerical stability of the system matrix +!> @param[in] ismpl local sample index + SUBROUTINE test_matrix(ismpl) + use arrays + use mod_genrl + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k + DOUBLE PRECISION k1, k2, k3, mindiff, max_val +! to small koeff. + PARAMETER (mindiff=1.0D-30) + PARAMETER (max_val=1.0D+150) + INTEGER fehler, nijk + INTRINSIC dabs + + nijk = i0*j0*k0 +! test about math stability + fehler = 0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 +! equal matrix lines, but different right sides ? + IF (i<i0) THEN + k1 = max_val + k2 = max_val + k3 = max_val + IF (d(i,j,k,ismpl)/=0.0D0) k1 = c(i+1,j,k,ismpl)/ & + d(i,j,k,ismpl) + IF (e(i,j,k,ismpl)/=0.0D0) k2 = d(i+1,j,k,ismpl)/ & + e(i,j,k,ismpl) + IF (w(i,j,k,ismpl)/=0.0D0) k3 = w(i+1,j,k,ismpl)/ & + w(i,j,k,ismpl) + IF ((a(i,j,k,ismpl)==0.0D0) .AND. (b(i,j,k, & + ismpl)==0.0D0) .AND. (c(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==a(i+1,j,k, & + ismpl)) .AND. (0.0D0==b(i+1,j,k,ismpl)) .AND. & !aw * (d(i,j,k,ismpl).eq.c(i+1,j,k,ismpl)).and. +!aw * (e(i,j,k,ismpl).eq.d(i+1,j,k,ismpl)).and. + (f(i,j,k,ismpl)==0.0D0) .AND. (g(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==e(i+1,j,k, & + ismpl)) .AND. (0.0D0==f(i+1,j,k, & + ismpl)) .AND. (0.0D0==g(i+1,j,k,ismpl)) .AND. & !aw * (W(i,j,k,ismpl).ne.W(i+1,j,k,ismpl)) + ((dabs(k1-k2)<mindiff) .AND. (dabs(k1-k3)> & + mindiff))) THEN + fehler = fehler + 1 + WRITE(*,*) ' ', i, j, k, ' i+1' + WRITE(*,*) 'D E | W' + WRITE(*,*) d(i,j,k,ismpl), e(i,j,k,ismpl), & + w(i,j,k,ismpl) + WRITE(*,*) 'C D | W' + WRITE(*,*) c(i+1,j,k,ismpl), d(i+1,j,k,ismpl), & + w(i+1,j,k,ismpl) + END IF + END IF +! + IF (j<j0) THEN + k1 = max_val + k2 = max_val + k3 = max_val + IF (d(i,j,k,ismpl)/=0.0D0) k1 = b(i,j+1,k,ismpl)/ & + d(i,j,k,ismpl) + IF (f(i,j,k,ismpl)/=0.0D0) k2 = d(i,j+1,k,ismpl)/ & + f(i,j,k,ismpl) + IF (w(i,j,k,ismpl)/=0.0D0) k3 = w(i,j+1,k,ismpl)/ & + w(i,j,k,ismpl) + IF ((a(i,j,k,ismpl)==0.0D0) .AND. (b(i,j,k, & + ismpl)==0.0D0) .AND. (c(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==a(i,j+1,k, & + ismpl)) .AND. (0.0D0==c(i,j+1,k,ismpl)) .AND. & !aw * (d(i,j,k,ismpl).eq.b(i,j+1,k,ismpl)).and. +!aw * (f(i,j,k,ismpl).eq.d(i,j+1,k,ismpl)).and. + (e(i,j,k,ismpl)==0.0D0) .AND. (g(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==e(i,j+1,k, & + ismpl)) .AND. (0.0D0==f(i,j+1,k, & + ismpl)) .AND. (0.0D0==g(i,j+1,k,ismpl)) .AND. & !aw * (W(i,j,k,ismpl).ne.W(i+1,j,k,ismpl)) + ((dabs(k1-k2)<mindiff) .AND. (dabs(k1-k3)> & + mindiff))) THEN + fehler = fehler + 1 + WRITE(*,*) ' ', i, j, k, ' j+1' + WRITE(*,*) 'D F | W' + WRITE(*,*) d(i,j,k,ismpl), f(i,j,k,ismpl), & + w(i,j,k,ismpl) + WRITE(*,*) 'B D | W' + WRITE(*,*) b(i,j+1,k,ismpl), d(i,j+1,k,ismpl), & + w(i,j+1,k,ismpl) + END IF + END IF +! + IF (k<k0) THEN + k1 = max_val + k2 = max_val + k3 = max_val + IF (d(i,j,k,ismpl)/=0.0D0) k1 = a(i,j,k+1,ismpl)/ & + d(i,j,k,ismpl) + IF (g(i,j,k,ismpl)/=0.0D0) k2 = d(i,j,k+1,ismpl)/ & + g(i,j,k,ismpl) + IF (w(i,j,k,ismpl)/=0.0D0) k3 = w(i,j,k+1,ismpl)/ & + w(i,j,k,ismpl) + IF ((a(i,j,k,ismpl)==0.0D0) .AND. (b(i,j,k, & + ismpl)==0.0D0) .AND. (c(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==c(i,j,k+1, & + ismpl)) .AND. (0.0D0==b(i,j,k+1,ismpl)) .AND. & !aw * (d(i,j,k,ismpl).eq.a(i,j,k+1,ismpl)).and. +!aw * (g(i,j,k,ismpl).eq.d(i,j,k+1,ismpl)).and. + (f(i,j,k,ismpl)==0.0D0) .AND. (e(i,j,k, & + ismpl)==0.0D0) .AND. (0.0D0==e(i,j,k+1, & + ismpl)) .AND. (0.0D0==f(i,j,k+1, & + ismpl)) .AND. (0.0D0==g(i,j,k+1,ismpl)) .AND. & !aw * (W(i,j,k,ismpl).ne.W(i+1,j,k,ismpl)) + ((dabs(k1-k2)<mindiff) .AND. (dabs(k1-k3)> & + mindiff))) THEN + fehler = fehler + 1 + WRITE(*,*) ' ', i, j, k, ' K+1' + WRITE(*,*) 'D G | W' + WRITE(*,*) d(i,j,k,ismpl), g(i,j,k,ismpl), & + w(i,j,k,ismpl) + WRITE(*,*) 'A D | W' + WRITE(*,*) a(i,j,k+1,ismpl), d(i,j,k+1,ismpl), & + w(i,j,k+1,ismpl) + END IF + END IF + END DO + END DO + END DO + IF (fehler>0) THEN + WRITE(*,*) & + 'error: inconsistent system, can not be solved ! (', & + fehler, & + ' linear lines with different right hand sides)' + STOP + END IF +! + RETURN + END diff --git a/solve/test_symmetry.f90 b/solve/test_symmetry.f90 new file mode 100644 index 0000000..fbdcec0 --- /dev/null +++ b/solve/test_symmetry.f90 @@ -0,0 +1,72 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief test the symmetry of the system matrix +!> @param[in] ismpl local sample index +!> @return true: when the matrix is symmetric + LOGICAL FUNCTION test_symmetry(ismpl) + use arrays + use mod_genrl + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i, j, k +! to small koeff. + INTEGER fehler + LOGICAL isit + +! test about symmetry + fehler = 0 + DO k = 1, k0 + DO j = 1, j0 + DO i = 1, i0 + IF (d(i,j,k,ismpl)/=0.0D0) THEN + IF (i>1) THEN + IF ((c(i,j,k,ismpl)/=e(i-1,j,k,ismpl)) .AND. (d(i-1, & + j,k,ismpl)/=0.0D0)) fehler = fehler + 1 + END IF + IF (j>1) THEN + IF ((b(i,j,k,ismpl)/=f(i,j-1,k,ismpl)) .AND. (d(i, & + j-1,k,ismpl)/=0.0D0)) fehler = fehler + 1 + END IF + IF (k>1) THEN + IF ((a(i,j,k,ismpl)/=g(i,j,k-1,ismpl)) .AND. (d(i,j, & + k-1,ismpl)/=0.0D0)) fehler = fehler + 1 + END IF + END IF + END DO + END DO + END DO +! + IF (fehler==0) THEN + IF (linfos(4)>=2) WRITE(*,*) ' Symmetric matrix !' + isit = .TRUE. + ELSE + IF (linfos(4)>=2) WRITE(*,*) ' Unsymmetric matrix with ', & + fehler, ' unsym. points !' + isit = .FALSE. + END IF +! + test_symmetry = isit +! + RETURN + END diff --git a/solve/test_zero.f90 b/solve/test_zero.f90 new file mode 100644 index 0000000..8d9247a --- /dev/null +++ b/solve/test_zero.f90 @@ -0,0 +1,81 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief zero test, is [v]=0 ? +!> @param[in] v variable to test +!> @param[in] code break code for debug +!> @param[out] divide_zero 0: not zero, [code]: if [v] is zero +!> @param[out] v modified to 1.0d0, if [v] is close to zero on entry + SUBROUTINE test_zero(v,code,divide_zero) + use arrays + IMPLICIT NONE +! stop if v=0 + DOUBLE PRECISION v + INTEGER code, divide_zero + INTRINSIC dabs + +! 3/4 of minimum value (not zero) + IF (dabs(v)<const_dble(2)) THEN + divide_zero = code + v = 1.0D0 + ELSE +! never change it bak +!AW divide_zero = 0 + END IF + RETURN + END + +!> @brief "Not A Number" test, is [v]="NAN" ? +!> @param[in] v variable to test +!> @return TRUE: if [v] is close to "NAN" + LOGICAL FUNCTION test_nan(v) + use arrays + IMPLICIT NONE +! stop if v=NAN + DOUBLE PRECISION v + INTRINSIC dabs + +! 3/4 of maximum value (not infinite) + IF (dabs(v)>const_dble(3)) THEN + test_nan = .TRUE. + ELSE + test_nan = .FALSE. + END IF + RETURN + END + +!> @brief zero test, is [v]=0 ? +!> @param[in] v variable to test +!> @return TRUE: if [v] is close to zero + LOGICAL FUNCTION test_null(v) + use arrays + IMPLICIT NONE + DOUBLE PRECISION v + INTRINSIC dabs + + IF (dabs(v)<const_dble(2)) THEN + test_null = .TRUE. + ELSE + test_null = .FALSE. + END IF + RETURN + END diff --git a/user/none/calc_user.f90 b/user/none/calc_user.f90 new file mode 100644 index 0000000..baa8c51 --- /dev/null +++ b/user/none/calc_user.f90 @@ -0,0 +1,57 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialisation routine, no "reinjection" functionality +!> @param[in] ismpl local sample index + SUBROUTINE user_init(ismpl) + use arrays + use mod_genrl + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i + + IF (linfos(3)>=2) WRITE(*,*) ' ... user_init (REINJECTION)' +! avoid side effects + DO i = 1, nbc_data +! init from the first set + dbc_dataold(i) = dbc_data(i,1,1) + END DO + RETURN + END + +!> @brief reinjection "dummy" routine, no "reinjection" functionality +!> @param[in] ismpl local sample index + SUBROUTINE calc_user(ismpl) + use arrays + use mod_genrl + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i + INTRINSIC int + + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_user' +! Dummy body + i = int(head(1,1,1,ismpl)) + RETURN + END diff --git a/user/none/user_check.f90 b/user/none/user_check.f90 new file mode 100644 index 0000000..9ec7a89 --- /dev/null +++ b/user/none/user_check.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current user directory choice +!> @param[in] ismpl local sample index + SUBROUTINE user_check(ismpl) + use mod_genrlc + IMPLICIT NONE + integer :: ismpl + character (len=20) :: ldef_user + PARAMETER (ldef_user='none') + logical :: test_option + EXTERNAL test_option + INTRINSIC trim + +#ifndef USER_none + WRITE(*,'(3A)') 'error: this source was written for USER=', & + ldef_user, ', please correct this check in "user_check.f"!' + STOP +#endif + IF ( .NOT. test_option('USER='//trim(def_user))) THEN + IF (ldef_user/=def_user) THEN + WRITE(*,'(7A)') 'error: model file needs an executable', & + ' build from USER=', trim(def_user), & + ', but the current', ' consist of USER=', & + trim(ldef_user), '!' + STOP + END IF + END IF + RETURN + END diff --git a/user/none/write_monitor_user.f90 b/user/none/write_monitor_user.f90 new file mode 100644 index 0000000..1ab1dd8 --- /dev/null +++ b/user/none/write_monitor_user.f90 @@ -0,0 +1,81 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes data in tecplot-format (example routine) +!> @param[in] otype orientation type:\n +!> - 1 new file\n +!> - 2 append\n +!> @param[in] ismpl local sample index + subroutine write_monitor_user(otype,ismpl) + + ! use mod_genrl, only: out_orientation + ! use mod_genrlc, only: project + ! use mod_time, only: simtime, tunit + + implicit none + + ! otype: + ! 1 new file + ! 2 append + integer, intent (in) :: otype + + ! Samples index + integer :: ismpl + + ! logical :: ltimes + ! logical :: lmonip + ! character (len=256) :: filename + ! integer, external :: lblank + + + ! ! Orientation of monitoring output + ! if (out_orientation==2 .or. out_orientation==3) then + ! ltimes = .true. + ! else + ! ltimes = .false. + ! end if + + ! if (out_orientation==4) then + ! lmonip = .true. + ! else + ! lmonip = .false. + ! end if + + ! ! Output Filename + ! call chln(project,i1,i2) + ! filename = project(i1:i2)//'_monitor_user.dat' + + ! if (ltimes) then + ! write(filename,'(2A,1e14.8,1A)') & + ! project(i1:i2),'_', & + ! (simtime(ismpl))/tunit,'_monitor_user.dat' + ! endif + + ! if (linfos(3).ge.2.and..not.lmonip) then + ! write(*,'(3A)') ' [W] : User Monitor points to "', & + ! filename(1:lblank(filename)),'"' + ! endif + + + return + + end subroutine write_monitor_user diff --git a/user/none/write_user.f90 b/user/none/write_user.f90 new file mode 100644 index 0000000..c6a4a0d --- /dev/null +++ b/user/none/write_user.f90 @@ -0,0 +1,65 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief special output defined by the developer of this working directory (example routine) +!> @param[in] ident iteration number +!> @param[in] ismpl local sample index +!> @details +!> This routine can be taken as a starting point for writing +!> additional user-defined output routines. + subroutine write_user(ident,ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + ! iteration number + integer, intent (in) ::ident + + ! common character variables + character (len=80) :: filename + character (len=8) :: snumber + + +! transform the typical suffix into a character variable for the filename + if (ident>=0) then + write(snumber,'(1I7)') ident + else if (ident==-1) then + write(snumber,'(A8)') 'final' + else if (ident==-2) then + write(snumber,'(A8)') 'debug' + else if (ident==-3) then + write(snumber,'(A8)') 'ens_mean' + else if (ident==-4) then + write(snumber,'(A8)') 'mean' + else if (ident==-5) then + write(snumber,'(A8)') 'ens_mean' + end if +! +! ----- begin main body ----- +! ... +! ------ end main body ------ +! + return + + end subroutine write_user diff --git a/user/wells3d/calc_user.f90 b/user/wells3d/calc_user.f90 new file mode 100644 index 0000000..5a61dd9 --- /dev/null +++ b/user/wells3d/calc_user.f90 @@ -0,0 +1,187 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief initialisation routine for reinjection +!> @param[in] ismpl local sample index + SUBROUTINE user_init(ismpl) + use arrays + use mod_genrl + use mod_linfos + IMPLICIT NONE + integer :: ismpl + integer :: i + + IF (linfos(3)>=2) WRITE(*,*) ' ... user_init (REINJECT-3D)' +! avoid side effects + DO i = 1, nbc_data +! init from the first set + dbc_dataold(i) = dbc_data(i,1,1) + END DO + RETURN + END + +!> @brief reinjection routine +!> @param[in] ismpl local sample index +!> @details +!>injection 1 13 8 5\n +!>injection 2 13 8 13\n +!>injection 3 13 8 21\n +!>production 1 13 18 5\n +!>production 2 13 18 13\n +!>production 3 13 18 21\n + SUBROUTINE calc_user(ismpl) + use arrays + use mod_genrl + use mod_time + use mod_linfos + use mod_wells3d + IMPLICIT NONE + integer :: ismpl + integer :: i, j + + + DOUBLE PRECISION tempc, pumpc, tempt, deltt + LOGICAL lbc_found, lbc_found1, lbc_found2 + DOUBLE PRECISION deltat + EXTERNAL deltat + INTRINSIC dabs + + + IF (linfos(3)>=2) WRITE(*,*) ' ... calc_user (REINJECT-3D)' + +!VR --- special case, danger !!! --- + + deltt = deltat(simtime(ismpl),ismpl) + IF ((simtime(ismpl)+deltt)/tunit>=stoptime) THEN + tempc = 0.D0 + pumpc = 0.D0 + tempt = 0.D0 +! for all productions + DO j = 1, num_pro + lbc_found = .FALSE. +! search in all boundary condition + DO i = 1, nbc_data + IF (ibc_data(i,cbc_i)==ipro(j) .AND. & + ibc_data(i,cbc_j)==jpro(j) .AND. & + ibc_data(i,cbc_k)==kpro(j) .AND. & + ibc_data(i,cbc_pv)==pv_head .AND. & + ibc_data(i,cbc_bt)==bt_neum) THEN + IF (dbc_data(i,1,ismpl)>=0.D0) THEN + WRITE(*,'(2A,3I8,1A)') 'error: HEAD Neumann-boundary& + & point for production', & + ' has a value >= 0.0 at [', ipro(j), jpro(j), & + kpro(j), '] !' + STOP + END IF + lbc_found = .TRUE. + tempc = tempc + conc(ipro(j),jpro(j),kpro(j),1,ismpl)* & + dabs(dbc_data(i,1,ismpl)) + tempt = tempt + temp(ipro(j),jpro(j),kpro(j),ismpl)* & + dabs(dbc_data(i,1,ismpl)) + pumpc = pumpc + dabs(dbc_data(i,1,ismpl)) + WRITE(*,'(1A,3(e12.4))') '!!!!! GPK2 center ', & + conc(ipro(j),jpro(j),kpro(j),1,ismpl), & + temp(ipro(j),jpro(j),kpro(j),ismpl), & + dbc_data(i,1,ismpl) + END IF + END DO + IF ( .NOT. lbc_found) THEN + WRITE(*,'(1A,3I8,1A)') 'error: no HEAD Neumann-boundary & + &point found for production [', ipro(j), jpro(j), & + kpro(j), '] !' + STOP + END IF + END DO + + IF (pumpc/=0.D0) THEN + tempc = tempc/pumpc + tempt = tempt/pumpc + END IF + + WRITE(*,'(4(1A,1e12.4))') '!!!!! reinjection rate = ', & + pumpc, ' l/s, concentration = ', tempc, & + ' mmol/l, temperature = ', tempt, ' C, time =', & + simtime(ismpl) + +! for all sources + DO j = 1, num_in + lbc_found = .FALSE. + lbc_found1 = .FALSE. + lbc_found2 = .FALSE. +! search in all boundary condition + DO i = 1, nbc_data + IF (ibc_data(i,cbc_i)==iin(j) .AND. & + ibc_data(i,cbc_j)==jin(j) .AND. & + ibc_data(i,cbc_k)==kin(j) .AND. & + ibc_data(i,cbc_pv)==pv_conc .AND. & + ibc_data(i,cbc_bt)==bt_diri .AND. & + ibc_data(i,cbc_si)==1) THEN + dbc_data(i,1,ismpl) = tempc + lbc_found = .TRUE. + END IF + IF (ibc_data(i,cbc_i)==iin(j) .AND. & + ibc_data(i,cbc_j)==jin(j) .AND. & + ibc_data(i,cbc_k)==kin(j) .AND. & + ibc_data(i,cbc_pv)==pv_temp .AND. & + ibc_data(i,cbc_bt)==bt_diri) THEN + dbc_data(i,1,ismpl) = tempt + lbc_found1 = .TRUE. + END IF + IF (ibc_data(i,cbc_i)==iin(j) .AND. & + ibc_data(i,cbc_j)==jin(j) .AND. & + ibc_data(i,cbc_k)==kin(j) .AND. & + ibc_data(i,cbc_pv)==pv_head .AND. & + ibc_data(i,cbc_bt)==bt_neum) THEN + dbc_data(i,1,ismpl) = pumpc + lbc_found2 = .TRUE. + END IF + END DO + IF ( .NOT. lbc_found) THEN + WRITE(*,'(1A,3I8,1A)') 'error: no CONC Dirichlet-boundar& + &y point found for injection [', iin(j), jin(j), & + kin(j), '] !' + STOP + END IF + IF ( .NOT. lbc_found1) THEN + WRITE(*,'(1A,3I8,1A)') 'error: no TEMP Dirichlet-boundar& + &y point found for injection [', iin(j), jin(j), & + kin(j), '] !' + STOP + END IF + IF ( .NOT. lbc_found2) THEN + WRITE(*,'(1A,3I8,1A)') 'error: no HEAD Dirichlet-boundar& + &y point found for injection [', iin(j), jin(j), & + kin(j), '] !' + STOP + END IF + END DO + ELSE +! reset the initial values + DO i = 1, nbc_data + dbc_data(i,1,ismpl) = dbc_dataold(i) + END DO + END IF + +!VR --- special case, danger !!! --- + + RETURN + END diff --git a/user/wells3d/mod_wells3d.f90 b/user/wells3d/mod_wells3d.f90 new file mode 100644 index 0000000..511973f --- /dev/null +++ b/user/wells3d/mod_wells3d.f90 @@ -0,0 +1,47 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief defines the reinjection parameters, user directory switch +module mod_wells3d +! number of IN sources + integer num_in + parameter (num_in = 1) +! number of OUT productions + integer num_pro + parameter (num_pro = 1) +! +! finish time + double precision stoptime +! 1d parameter (stoptime = 86400.d0) +! 19 h!!! + parameter (stoptime = 68400.d0) +! + integer iin(num_in), jin(num_in), kin(num_in) + integer ipro(num_pro), jpro(num_pro), kpro(num_pro) +! + data iin /13/ + data jin /8/ + data kin /13/ + data ipro /13/ + data jpro /18/ + data kpro /13/ +end module mod_wells3d diff --git a/user/wells3d/user_check.f90 b/user/wells3d/user_check.f90 new file mode 100644 index 0000000..23a6658 --- /dev/null +++ b/user/wells3d/user_check.f90 @@ -0,0 +1,50 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief check current user directory choice +!> @param[in] ismpl local sample index + SUBROUTINE user_check(ismpl) + use mod_genrlc + IMPLICIT NONE + INTEGER ismpl + character (len=20) :: ldef_user + PARAMETER (ldef_user='wells3d') + LOGICAL test_option + EXTERNAL test_option + INTRINSIC trim + +#ifndef USER_wells3d + WRITE(*,'(3A)') 'error: this source was written for USER=', & + ldef_user, ', please correct this check in "user_check.f"!' + STOP +#endif + IF ( .NOT. test_option('USER='//trim(def_user))) THEN + IF (ldef_user/=def_user) THEN + WRITE(*,'(7A)') 'error: model file needs an executable', & + ' build from USER=', trim(def_user), & + ', but the current', ' consist of USER=', & + trim(ldef_user), '!' + STOP + END IF + END IF + RETURN + END diff --git a/user/wells3d/write_monitor_user.f90 b/user/wells3d/write_monitor_user.f90 new file mode 100644 index 0000000..1ab1dd8 --- /dev/null +++ b/user/wells3d/write_monitor_user.f90 @@ -0,0 +1,81 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief writes data in tecplot-format (example routine) +!> @param[in] otype orientation type:\n +!> - 1 new file\n +!> - 2 append\n +!> @param[in] ismpl local sample index + subroutine write_monitor_user(otype,ismpl) + + ! use mod_genrl, only: out_orientation + ! use mod_genrlc, only: project + ! use mod_time, only: simtime, tunit + + implicit none + + ! otype: + ! 1 new file + ! 2 append + integer, intent (in) :: otype + + ! Samples index + integer :: ismpl + + ! logical :: ltimes + ! logical :: lmonip + ! character (len=256) :: filename + ! integer, external :: lblank + + + ! ! Orientation of monitoring output + ! if (out_orientation==2 .or. out_orientation==3) then + ! ltimes = .true. + ! else + ! ltimes = .false. + ! end if + + ! if (out_orientation==4) then + ! lmonip = .true. + ! else + ! lmonip = .false. + ! end if + + ! ! Output Filename + ! call chln(project,i1,i2) + ! filename = project(i1:i2)//'_monitor_user.dat' + + ! if (ltimes) then + ! write(filename,'(2A,1e14.8,1A)') & + ! project(i1:i2),'_', & + ! (simtime(ismpl))/tunit,'_monitor_user.dat' + ! endif + + ! if (linfos(3).ge.2.and..not.lmonip) then + ! write(*,'(3A)') ' [W] : User Monitor points to "', & + ! filename(1:lblank(filename)),'"' + ! endif + + + return + + end subroutine write_monitor_user diff --git a/user/wells3d/write_user.f90 b/user/wells3d/write_user.f90 new file mode 100644 index 0000000..c6a4a0d --- /dev/null +++ b/user/wells3d/write_user.f90 @@ -0,0 +1,65 @@ +! MIT License +! +! Copyright (c) 2020 SHEMAT-Suite +! +! Permission is hereby granted, free of charge, to any person obtaining a copy +! of this software and associated documentation files (the "Software"), to deal +! in the Software without restriction, including without limitation the rights +! to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +! copies of the Software, and to permit persons to whom the Software is +! furnished to do so, subject to the following conditions: +! +! The above copyright notice and this permission notice shall be included in all +! copies or substantial portions of the Software. +! +! THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +! IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +! FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +! AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +! LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +! OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +! SOFTWARE. + +!> @brief special output defined by the developer of this working directory (example routine) +!> @param[in] ident iteration number +!> @param[in] ismpl local sample index +!> @details +!> This routine can be taken as a starting point for writing +!> additional user-defined output routines. + subroutine write_user(ident,ismpl) + + implicit none + + ! Sample index + integer :: ismpl + + ! iteration number + integer, intent (in) ::ident + + ! common character variables + character (len=80) :: filename + character (len=8) :: snumber + + +! transform the typical suffix into a character variable for the filename + if (ident>=0) then + write(snumber,'(1I7)') ident + else if (ident==-1) then + write(snumber,'(A8)') 'final' + else if (ident==-2) then + write(snumber,'(A8)') 'debug' + else if (ident==-3) then + write(snumber,'(A8)') 'ens_mean' + else if (ident==-4) then + write(snumber,'(A8)') 'mean' + else if (ident==-5) then + write(snumber,'(A8)') 'ens_mean' + end if +! +! ----- begin main body ----- +! ... +! ------ end main body ------ +! + return + + end subroutine write_user diff --git a/version.inc.in b/version.inc.in new file mode 100644 index 0000000..0152c66 --- /dev/null +++ b/version.inc.in @@ -0,0 +1,15 @@ +! this file will be generated automatically - change the Makefile !!! +! current version + character version*80 + parameter (version = "@PROJECT_NAME@ @PROJECT_VERSION@ (@PROJECT_DESCRIPTION@)") +! current date + character datum*40 + parameter (datum = "@_configuration_time@") +! build command line + character makecmd*256 + parameter (makecmd = & + "PROPS=@PROPS@ "// & + "USER=@USER@ "// & + "COMPTYPE=@COMPTYPE@ "// & + "") + -- GitLab