! Copyright (c) 2011-2016,2020 Harald Klimach <harald.klimach@uni-siegen.de> ! Copyright (c) 2011-2016,2021-2022 Kannan Masilamani <kannan.masilamani@uni-siegen.de> ! Copyright (c) 2012-2013 Simon Zimny <s.zimny@grs-sim.de> ! Copyright (c) 2012-2014 Jens Zudrop <j.zudrop@grs-sim.de> ! Copyright (c) 2012-2013 Manuel Hasert <m.hasert@grs-sim.de> ! Copyright (c) 2012, 2015-2016 Jiaxing Qi <jiaxing.qi@uni-siegen.de> ! Copyright (c) 2013-2015 Nikhil Anand <nikhil.anand@uni-siegen.de> ! Copyright (c) 2014 Julia Moos <julia.moos@student.uni-siegen.de> ! Copyright (c) 2015-2016, 2020 Peter Vitt <peter.vitt2@uni-siegen.de> ! Copyright (c) 2016 Tobias Schneider <tobias1.schneider@student.uni-siegen.de> ! Copyright (c) 2019 Neda Ebrahimi Pour <neda.epour@uni-siegen.de> ! ! Redistribution and use in source and binary forms, with or without ! modification, are permitted provided that the following conditions are met: ! ! 1. Redistributions of source code must retain the above copyright notice, this ! list of conditions and the following disclaimer. ! ! 2. Redistributions in binary form must reproduce the above copyright notice, ! this list of conditions and the following disclaimer in the documentation ! and/or other materials provided with the distribution. ! ! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" ! AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE ! IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE ! DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE ! FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL ! DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR ! SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER ! CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, ! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE ! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ! ****************************************************************************** !> Spatial functions let you describe functions that may vary in space. !! The are needed for initial conditions and volumetric information like !! source terms. !! A space-time function that depends also on time can be constructed by !! the space-time function of kind `combined`, see the !! [[tem_spacetime_fun_module]]. !! !! The spatial functions may be constants, various predefined functions, or !! arbitrary Lua functions that depend on the three space coordinates. !! In the Lua script, the spatial function is either a constant scalar number, !! a Lua function, or a table. !! !! If it is a table, it either is a constant definition for a vector value, !! for example a velocity definition, or it is a table that contains a !! definition of either a `fun`, `const` or `predefined` key. !! Here, `fun` would in turn need to be a Lua function, and const the definition !! of constant values (either a scalar, or a vector in a table). !! The `predefined` key signals the use of one of the available predefined !! functions and further parameters for their definition depend on the !! respective functions. !! !! Available predefined functions are: !! !! - 'crvpx' [[tem_ic_predefs_module:load_ic_2dcrvp]] !! - 'crvpy' [[tem_ic_predefs_module:load_ic_2dcrvp]] !! - 'crvppressure' [[tem_ic_predefs_module:load_ic_2dcrvp]] !! - 'cylindricalwave' [[tem_cylindricalWave_module]] !! - 'gausspulse' [[tem_ic_predefs_module:load_spatial_random]] !! - 'heaviside_gibbs' !! [[tem_heaviside_gibbs_fun_module:tem_load_heaviside_gibbs]] !! - 'miescatter_magneticfieldx' [[tem_miescatter_module:tem_load_miescatter]] !! - 'miescatter_magneticfieldy' [[tem_miescatter_module:tem_load_miescatter]] !! - 'parabol' [[tem_spatial_module:load_spatial_parabol]] !! - 'pml' [[tem_pmlLayer_module]] !! - 'polygon_material' [[tem_polygon_material_module]] !! - 'polygon_material_3d' [[tem_polygon_material_module]] !! - 'random' [[tem_spatial_module:load_spatial_random]] !! - 'rectangular' !! - 'spongelayer_plane' [[tem_spongeLayer_module]] !! - 'spongelayer_plane_1d' [[tem_spongeLayer_module]] !! - 'viscous_spongelayer_radial' [[tem_spongeLayer_module:tem_load_spongeLayer_radial]] !! - 'viscous_spongelayer_radial_2d' [[tem_spongeLayer_module:tem_load_spongeLayer_radial]] !! - 'viscous_spongelayer_box' [[tem_spongeLayer_module:tem_load_spongeLayer_box]] !! - 'viscous_spongelayer_box_2d' [[tem_spongeLayer_module:tem_load_spongeLayer_box]] !! - 'spongelayer_box' [[tem_spongeLayer_module:tem_load_spongeLayer_box]] !! - 'spongelayer_box' [[tem_spongeLayer_module:tem_load_spongeLayer_box]] !! - 'spongelayer_box_2d' [[tem_spongeLayer_module:tem_load_spongeLayer_box]] !! - 'spongelayer_radial' [[tem_spongeLayer_module:tem_load_spongeLayer_radial]] !! - 'tgv_p' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_ux' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_uy' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_sxx' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_sxz' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_syy' [[tem_ic_predefs_module:load_ic_tgv]] !! - 'tgv_syz' [[tem_ic_predefs_module:load_ic_tgv]] !! !! The simplest spatial function definition is just a constant scalar number: !! !!```lua !! spatial = 1.0 !!``` !! !! Similarly the definition of a spatial function by a Lua function can simply !! be written as !! !!```lua !! spatial = fun(x,y,z) !! return x*y*z !! end fun !!``` !! !! The Lua function needs to take 3 arguments, representing the three spatial !! coordinates. !! !! An example for the definition of a predefined function can take the following !! form: !! !!```lua !! spatial = { !! predefined = 'random', !! min = 0, !! max = 1 !! } !!``` !! module tem_spatial_module ! include treelm modules use env_module, only: rk, long_k, LabelLen, globalMaxLevels use tem_aux_module, only: tem_abort use tem_tools_module, only: upper_to_lower use treelmesh_module, only: treelmesh_type use tem_geometry_module, only: tem_BaryOfId use tem_canonicalND_module, only: tem_canonicalND_type use tem_shape_module, only: tem_shape_type, tem_load_shape use tem_pointData_module, only: tem_grwPoints_type use tem_ic_predefs_module, only: ic_gausspulse_type, load_ic_gausspulse, & & ic_gausspulse_for, & & ic_2dcrvp_type, load_ic_2dcrvp, & & ic_2dcrvpX_for, ic_2dcrvpY_for, & & ic_2dcrvpPressure_for, & & ic_tgv_type, load_ic_tgv, & & ic_tgv_pressure_for, & & ic_tgv_ux_for, ic_tgv_uy_for, & & ic_tgv_Sxx_for, ic_tgv_Syy_for, & & ic_tgv_Sxz_for, ic_tgv_Syz_for use tem_logging_module, only: logUnit, tem_toStr use tem_grow_array_module, only: grw_realArray_type, append, truncate use tem_miescatter_module, only: tem_miescatter_field_type, & & tem_load_miescatter_displacementfieldz, & & tem_load_miescatter_magneticfieldx, & & tem_load_miescatter_magneticfieldy, & & tem_eval_miescatter_displz, & & tem_eval_miescatter_magnx, & & tem_eval_miescatter_magny use tem_heaviside_gibbs_fun_module, only: tem_heaviside_gibbs_type, & & tem_load_heaviside_gibbs, & & tem_eval_heaviside_gibbs use tem_pmlLayer_module, only: tem_pmlLayer_type, & & tem_evaluate_pml, & & tem_load_pmlLayer use tem_cylindricalWave_module, only: tem_cylindricalWave_type, & & tem_load_cylindricalWave, & & tem_eval_cylindricalWave use tem_polygon_material_module, only: tem_polygon_material_type, & & tem_polygon_material_load, & & tem_eval_polygon_material, & & tem_eval_polygon_material_3d, & & tem_eval_polygon_material_scal, & & tem_eval_polygon_material_scal_3d use tem_spongeLayer_module, only: tem_spongeLayer_plane_type, & & tem_spongeLayer_radial_type, & & tem_spongeLayer_box_type, & & tem_load_spongeLayer_plane, & & tem_load_spongeLayer_radial, & & tem_load_spongeLayer_box, & & tem_spongeLayer_plane_for, & & tem_spongeLayer_box_for, & & tem_spongeLayer_box2d_for, & & tem_spongeLayer_radial_for, & & tem_viscSpongeLayer_plane_for, & & tem_viscSpongeLayer_radial_for, & & tem_viscSpongelayer_box_for, & & tem_viscSpongelayer_box2d_for ! include aotus modules use aotus_module, only: flu_State, aoterr_Fatal, aoterr_NonExistent, & & aoterr_WrongType, aot_top_get_val, aot_get_val use aot_table_module, only: aot_table_open, aot_table_close use aot_fun_module, only: aot_fun_type, aot_fun_open, aot_fun_close, & & aot_fun_put, aot_fun_do use aot_references_module, only: aot_reference_for implicit none private real(kind=rk) :: ref_amp = 1.0_rk public :: tem_spatial_type public :: tem_load_spatial public :: tem_spatial_lua_for public :: tem_spatial_parabol3d_for public :: tem_spatial_parabol2d_for public :: tem_spatial_for public :: tem_spatial_storeVal !> stores values of spatial term during initialization to reduce !! computations during main loop. type spatial_value_type !> Evaluated variable value on each point. !! For vectorial variable, the values are stored as !! (iVal-1)*nComp + iComp type(grw_realArray_type) :: evalVal end type spatial_value_type !> defines parabola functions !! shape kind defines 2d or 3d parabola type spatial_parabol_type !> define point, line or plane spatial profile type( tem_shape_type ) :: geometry !> magnitude of the spatial value real(kind=rk), allocatable :: amplitude(:) end type spatial_parabol_type !> Defines a random spatial distribution within a given interval. type spatial_random_type !> Minimal value to produce real(kind=rk) :: val_min !> Maximal value to produce real(kind=rk) :: val_max !> Length of the value interval real(kind=rk) :: val_range end type spatial_random_type !> Defines a stationary solution of the Euler equation by the Hopf Fibration. type spatial_hopf_type !> Minimal value to produce real(kind=rk) :: radius !> Maximal value to produce real(kind=rk) :: p0 end type spatial_hopf_type !> contains spatial state information type tem_spatial_type !> kind: how is the spatial defined? !! !! - 'none' = no spatial modifier defined !! - 'const' = a constant factor !! - 'lua_fun' = defined as a lua function !! - 'parabol' = parabolic function !! shape = {object = line} defines 2d parabola !! shape = {object = plane} defines 3d parabola !! Further predefined functions might be added here character(len=LabelLen) :: kind !> constant spatial value for nComponents real(kind=rk), allocatable :: const(:) !> Reference to the Lua function if the spatial function is defined !! as a Lua function. integer :: lua_fun_ref = 0 type(flu_state) :: conf !> defines gausspulse type( ic_gausspulse_type ) :: gausspulse !> 2d co-rotating vortex pair type( ic_2dcrvp_type ) :: crvp !> Taylor-Green vortex type type( ic_tgv_type ) :: tgv !> Parabol type type( spatial_parabol_type ) :: parabol !> Random type type( spatial_random_type ) :: random !> Hopf Fibration type type( spatial_hopf_type ) :: hopf !> Spatial function for Mie-series solution !! of electrodynamic scattering at dielectric sphere. type(tem_miescatter_field_type) :: mie_fun !> Spatial function for Heaviside function including Gibbs !! oscillations. type(tem_heaviside_gibbs_type) :: heaviside_gibbs_fun !> store spatial value on each level type(spatial_value_type) :: valOnLvl(globalMaxLevels) !> type for the plane sponge layer type(tem_spongeLayer_plane_type) :: spongePlane !> type for the box sponge layer type(tem_spongeLayer_box_type) :: spongeBox !> type for the radial sponge layer type(tem_spongeLayer_radial_type) :: spongeRadial !> type for the pml damping medium type(tem_pmlLayer_type) :: pml !> type for a scalar cylindrical wave. type(tem_cylindricalWave_type) :: cylindricalWave !> Description of a material definition by a polygon. type(tem_polygon_material_type) :: polygon_material !> range of x and y dimention for rectangular function real(kind=rk) :: rect_ly real(kind=rk) :: rect_lz !> to store spatial values during initialization logical :: isStored = .false. end type tem_spatial_type interface tem_spatial_lua_for module procedure tem_spatial_lua_for_treeIDs module procedure tem_spatial_lua_for_coord module procedure tem_spatial_lua_for_index module procedure tem_spatial_lua_vector_for_treeIDs module procedure tem_spatial_lua_vector_for_coord module procedure tem_spatial_lua_vector_for_index end interface tem_spatial_lua_for interface tem_spatial_parabol2d_for module procedure tem_spatial_parabol2d_for_treeIDs module procedure tem_spatial_parabol2d_for_coord end interface tem_spatial_parabol2d_for interface tem_spatial_parabol3d_for module procedure tem_spatial_parabol3d_for_treeIDs module procedure tem_spatial_parabol3d_for_coord end interface tem_spatial_parabol3d_for interface tem_spatial_for module procedure tem_spatial_for_treeIDs module procedure tem_spatial_for_coord module procedure tem_spatial_vector_for_treeIDs module procedure tem_spatial_vector_for_coord module procedure tem_spatial_scalar_for_index module procedure tem_spatial_vector_for_index end interface tem_spatial_for interface tem_spatial_storeVal module procedure tem_spatial_scalar_storeVal module procedure tem_spatial_vector_storeVal end interface tem_spatial_storeVal contains ! ------------------------------------------------------------------------ ! !> This subroutine load spatial boundary state variable. !! !! If spatial is defined as block than read block for predefined Fortran !! function variables else it is defined as constant. !! Valid definitions: !! !! - Constant !!```lua !! spatial = 1.0 !!``` !! - lua_function !!```lua !! spatial = lua_fun_name !!``` !! - define lua function inside a table !!```lua !! spatial = {fun=lua_fun_name, store=<>} !!``` !! Note. Lua function take 3 input arguments (x,y,z) i.e barycentric !! coordinates of an element !! - Predefined Fortran function !!```lua !! spatial = {predefined = "fun_name", fun_parameters} !!``` !! example given in subroutine [[load_spatial_parabol]] definition !! subroutine tem_load_spatial( me, conf, parent, key, defaultValue, nComp, & & errCode ) ! -------------------------------------------------------------------- ! !> spatial boundary state type type(tem_spatial_type), intent(out) :: me !> lua state type type(flu_State) :: conf !> aotus parent handle integer, intent(in) :: parent !> state variable key string defined in lua character(len=*), intent(in), optional :: key !> What should be set s a default value for the quantities if no !! quantity was given in the lua file real(kind=rk), intent(in), optional :: defaultValue !> number of components of the variable integer, intent(in), optional :: nComp !> Error code from lua loading integer, intent(out), optional :: errCode ! -------------------------------------------------------------------- ! integer :: thandle, iError integer :: loc_nComp type(aot_fun_type) :: fun character(len=labelLen) :: local_key real(kind=rk) :: local_default logical :: loadasConst ! -------------------------------------------------------------------- ! if( present( nComp ))then loc_nComp = nComp else loc_nComp = 1 end if if(present(defaultValue)) then local_default = defaultValue else local_default = 1._rk endif if(present(key)) then local_key = trim(key) else local_key = 'spatial' endif write(logUnit(1),"(A)") 'Loading spatial for '//trim(local_key) ! default values loadasConst = .false. ! First test for a lua function call aot_fun_open(L=conf, parent=parent, fun=fun, key=trim(local_key)) me%conf = conf if_fun: if (fun%handle /= 0) then ! There was a function found for the spatial entry, go on using it me%kind = 'lua_fun' ! Create a reference for this function and store it. me%lua_fun_ref = aot_reference_for(conf) call aot_fun_close( L=conf, fun=fun ) iError = 0 else ! Not a LUA function call aot_fun_close( L=conf, fun=fun ) ! Not a function, try to interpret it as a table' call aot_table_open( L = conf, & & thandle = thandle, & & parent = parent, & & key = trim(local_key) ) ! table is defined if_table: if (thandle /= 0) then ! check whether to store spatial values during initialization or not call aot_get_val( L = conf, & & thandle = thandle, & & key = 'store', & & val = me%isStored, & & default = .false., & & ErrCode = iError ) ! inside table try to open lua function with key 'fun' call aot_fun_open( L = conf, & & parent = thandle, & & fun = fun, & & key = 'fun' ) ! lua function defined with key 'fun' if (fun%handle /= 0) then me%kind = 'lua_fun' ! Create a reference for this function and store it. me%lua_fun_ref = aot_reference_for(conf) call aot_fun_close( L=conf, fun=fun ) iError = 0 else call aot_fun_close( L=conf, fun=fun ) ! Not a lua function with key 'fun'. ! Try to interpret it as a predefined' call aot_get_val( L = conf, & & thandle = thandle, & & key = 'predefined', & & val = me%kind, & & default = 'unknown', & & ErrCode = iError ) if( btest(iError, aoterr_WrongType) ) then call tem_abort('Error in retrieving the function kind.') end if ! predefined key word is not defined. ! try to interpret as constant with key "const" if ( btest(iError, aoterr_NonExistent) ) then call load_spatial_asConst( const = me%const, & & conf = conf, & & errCode = iError, & & parent = thandle, & & key = 'const', & & nComp = loc_nComp ) if (iError == 0) then me%kind = 'const' else call aot_table_close( L=conf, thandle=thandle ) ! Constant is not defined with key "const" ! Try to interpret directly from local_key loadasConst = .true. end if else ! predefined exist call load_spatial_predefined( me = me, & & conf = conf, & & thandle = thandle, & & nComp = loc_nComp ) iError = 0 end if ! not predefined end if ! not lua_fun with key "fun" else ! not a table try to interprect as constant loadasConst = .true. end if if_table call aot_table_close( L=conf, thandle=thandle ) end if if_fun if (loadasConst) then ! Not a table with specific key word like "fun", "const", "predefined" ! Try to interpret it as a constant with key write(logUnit(7),"(A)") 'Try to load as constant with key ' & & // trim(local_key) call load_spatial_asConst( const = me%const, & & conf = conf, & & errCode = iError, & & parent = parent, & & key = trim(local_key), & & nComp = loc_nComp ) if (iError == 0) then me%kind = 'const' else write(logUnit(1),"(A)") ' WARNING: variable is non-existent!' write(logUnit(1),"(A)") ' Setting kind to be "none" and value = ' & & // trim( tem_toStr(local_default) ) & & // ' for all ' // & & trim( tem_toStr(loc_nComp) ) // ' components' if (allocated(me%const)) deallocate(me%const) allocate(me%const(loc_nComp)) me%const = local_default me%kind = 'none' end if end if write(logUnit(3),"(A)") ' Spatial for ' // trim(local_key) & & // ' is a defined as ' // trim(me%kind) if (trim(me%kind) == 'const') then if ( loc_nComp == 1 ) then write(logUnit(3),"(A)") 'value = ' // trim(tem_toStr(me%const(1))) else write(logUnit(3),"(A)") 'value = ' & & // trim(tem_toStr(me%const(1:loc_nComp),',')) end if end if if (present(errCode)) errCode = iError end subroutine tem_load_spatial ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> Load spatial as constant subroutine load_spatial_asConst( const, conf, errCode, parent, key, nComp ) ! -------------------------------------------------------------------- ! !> value to be filled real(kind=rk), allocatable :: const(:) !> lua state type type(flu_State) :: conf !> errCode = -1, if spatial function is not defined as constant integer, intent(out) :: errCode !> aotus parent handle integer, intent(in) :: parent !> key is either "local_key" or "const" character(len=*), intent(in) :: key !> number of components of the variable integer, intent(in) :: nComp ! -------------------------------------------------------------------- ! integer, allocatable :: vError(:), vErr_NonExistent(:), vErr_WrongType(:) ! -------------------------------------------------------------------- ! errCode = 0 if (nComp == 1) then write(logUnit(5),*) 'Load spatial as single constant' allocate(const(nComp), vError(nComp)) call aot_get_val( L = conf, & & thandle = parent, & & val = const(1), & & key = key, & & ErrCode = vError(1) ) if (btest(vError(1), aoterr_NonExistent)) then ! if previous checks fails return errCode =-1 ! and set default kind = none and value = 1 write(logUnit(3),*) 'ERROR: Fatal error occured in loading ' & & // 'scalar constants' errCode = -1 return end if else !nComp > 1 write(logUnit(3),"(A,I0)") & & 'Load spatial as array of constant with nComp ', nComp !Try to load constant of nComp call aot_get_val( L = conf, & & thandle = parent, & & val = const, & & maxLength = nComp, & & key = key, & & ErrCode = vError ) if (size(const) == 0) then write(logUnit(3),*) 'Error loading array constant from key "'& & // trim(key) // '"' errCode = -1 return else ! if any error index is fatal then return errCode - 1 allocate(vErr_NonExistent(size(vError))) vErr_NonExistent = aoterr_NonExistent if(any(btest(vError, vErr_NonExistent))) then write(logUnit(3),*) 'ERROR: Fatal error occured in loading ' & & // 'array of constants with nComp:', nComp errCode = -1 return else if (size(const) /= nComp) then ! no fatal error but number of constant defined /= nComp write(logUnit(1),*) 'Spatial as constant. table size /= nComp', & & nComp call tem_abort() end if end if end if allocate(vErr_WrongType(size(vError))) vErr_WrongType = aoterr_WrongType if (any(btest(vError, vErr_WrongType))) then write(logUnit(1),*)'FATAL Error occured in definition of ' & & // 'the spatial' write(logUnit(1),*)'while retrieving spatial constant:' write(logUnit(1),*)'Variable has wrong type (should be a ' & & // 'real number)!' call tem_abort() end if end subroutine load_spatial_asConst ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> Load predefined spatial function subroutine load_spatial_predefined( me, conf, thandle, nComp ) ! -------------------------------------------------------------------- ! !> spatial fun information type(tem_spatial_type), intent(inout) :: me !> lua state type type(flu_State) :: conf !> spatial function handle integer, intent(in) :: thandle !> Number of components integer, intent(in) :: nComp ! -------------------------------------------------------------------- ! integer :: nDim, iError character(len=labelLen) :: funkind ! -------------------------------------------------------------------- ! write(logUnit(1),*) 'Spatial is defined as predefined:' funkind = adjustl(me%kind) funkind = upper_to_lower(funkind) select case(trim(funkind)) case('parabol') write(logUnit(3),*) ' is a parabolic profile' call load_spatial_parabol( me = me%parabol, & & conf = conf, & & thandle = thandle, & & nComp = nComp ) case('random') write(logUnit(3),*) ' is a random distribution' call load_spatial_random( me = me%random, & & conf = conf, & & thandle = thandle ) case('gausspulse') write(logUnit(3),*) ' is a gaussian pulse' call load_ic_gausspulse( conf = conf, & & thandle = thandle, & & me = me%gausspulse ) case('tgv_p') write(logUnit(5),*) ' is a Taylor-Green vortex pressure' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_ux') write(logUnit(5),*) ' is a Taylor-Green vortex Ux' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_uy') write(logUnit(5),*) ' is a Taylor-Green vortex Uy' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_sxx') write(logUnit(5),*) ' is a Taylor-Green vortex Sxx' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_syy') write(logUnit(5),*) ' is a Taylor-Green vortex Syy' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_syz') write(logUnit(5),*) ' is a Taylor-Green vortex Syz' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) case('tgv_sxz') write(logUnit(5),*) ' is a Taylor-Green vortex Sxz' call load_ic_tgv( conf = conf, & & thandle = thandle, & & me = me%tgv ) !HK: Not implemented yet. !HK! case('hopf') !HK! write(logUnit(1),*) ' is a Hopf fibration solution' !HK! call load_spatial_hopf( me = me%hopf, conf = conf, & !HK! & thandle = thandle ) case('crvpx') write(logUnit(3),*) ' is a Spinning vortex pair X component' call load_ic_2dcrvp( conf = conf, & & thandle = thandle, & & me = me%crvp ) case('crvpy') write(logUnit(3),*) ' is a Spinning vortex pair Y component' call load_ic_2dcrvp( conf = conf, & & thandle = thandle, & & me = me%crvp ) case('crvppressure') write(logUnit(3),*) ' is a Spinning vortex pair density' call load_ic_2dcrvp( conf = conf, & & thandle = thandle, & & me = me%crvp ) case('miescatter_displacementfieldz') call tem_load_miescatter_displacementfieldz( conf = conf, & & thandle = thandle, & & me = me%mie_fun ) case('miescatter_magneticfieldx') call tem_load_miescatter_magneticfieldx( conf = conf, & & thandle = thandle, & & me = me%mie_fun ) case('miescatter_magneticfieldy') call tem_load_miescatter_magneticfieldy( conf = conf, & & thandle = thandle, & & me = me%mie_fun ) case('heaviside_gibbs') call tem_load_heaviside_gibbs( conf = conf, & & thandle = thandle, & & me = me%heaviside_gibbs_fun ) case('spongelayer_plane') ndim = 3 call tem_load_spongeLayer_plane( conf = conf, & & thandle = thandle, & & me = me%spongePlane, & & ndim = ndim, & & nComp = nComp ) case('spongelayer_plane_2d') ndim = 2 call tem_load_spongeLayer_plane( conf = conf, & & thandle = thandle, & & me = me%spongePlane, & & ndim = ndim, & & nComp = nComp ) case('spongelayer_plane_1d') ndim = 1 call tem_load_spongeLayer_plane( conf = conf, & & thandle = thandle, & & me = me%spongePlane, & & ndim = ndim, & & nComp = nComp ) case('spongelayer_radial') write(logUnit(3),*) ' is a radial sponge layer' ndim = 3 call tem_load_spongelayer_radial( me = me%spongeRadial, & & conf = conf, & & thandle = thandle, & & nDim = nDim, & & nComp = nComp ) case('spongelayer_radial_2d') write(logUnit(3),*) ' is a 2d radial sponge layer' ndim = 2 call tem_load_spongelayer_radial( me = me%spongeRadial, & & conf = conf, & & thandle = thandle, & & nDim = nDim, & & nComp = nComp ) case('spongelayer_box') call tem_load_spongeLayer_box( conf = conf, & & thandle = thandle, & & me = me%spongeBox, & & ndim = 3, & & nComp = nComp ) case('spongelayer_box_2d') call tem_load_spongeLayer_box( conf = conf, & & thandle = thandle, & & me = me%spongeBox, & & ndim = 2, & & nComp = nComp ) case('viscous_spongelayer_plane') ndim = 3 call tem_load_spongeLayer_plane( conf = conf, & & thandle = thandle, & & me = me%spongePlane, & & ndim = nDim, & & nComp = nComp, & & stateName = 'viscosity' ) case('viscous_spongelayer_box') ndim = 3 call tem_load_spongeLayer_box( conf = conf, & & thandle = thandle, & & me = me%spongeBox, & & ndim = nDim, & & nComp = nComp, & & stateName = 'viscosity' ) case('viscous_spongelayer_box_2d') ndim = 2 call tem_load_spongeLayer_box( conf = conf, & & thandle = thandle, & & me = me%spongeBox, & & ndim = nDim, & & nComp = nComp, & & stateName = 'viscosity' ) case('viscous_spongelayer_radial') write(logUnit(3),*) ' is a radial viscous sponge layer' nDim = 3 call tem_load_spongelayer_radial( me = me%spongeRadial, & & conf = conf, & & thandle = thandle, & & nDim = nDim, & & nComp = nComp, & & stateName = 'viscosity' ) case('viscous_spongelayer_radial_2d') write(logUnit(3),*) ' is a 2d radial viscous sponge layer' nDim = 2 call tem_load_spongelayer_radial( me = me%spongeRadial, & & conf = conf, & & thandle = thandle, & & nDim = nDim, & & nComp = nComp, & & stateName = 'viscosity' ) case('pml') call tem_load_pmlLayer( conf = conf, & & thandle = thandle, & & me = me%pml ) case('cylindricalwave') call tem_load_cylindricalWave( conf = conf, & & thandle = thandle, & & me = me%cylindricalWave ) case('polygon_material','polygon_material_3d') call tem_polygon_material_load( conf = conf, & & thandle = thandle, & & me = me%polygon_material ) case('rectangular', 'gate') call aot_get_val( L = conf, & & thandle = thandle, & & key = 'ly', & & val = me%rect_ly, & & ErrCode = iError, & & default = 0.5_rk ) call aot_get_val( L = conf, & & thandle = thandle, & & key = 'lz', & & val = me%rect_lz, & & ErrCode = iError, & & default = 0.5_rk ) write(logUnit(3),"(A)") ' this is a predefined rectangular shape' write(logUnit(3),"(A)") ' ly: '//trim(tem_toStr(me%rect_ly)) write(logUnit(3),"(A)") ' lz: '//trim(tem_toStr(me%rect_lz)) case default write(logUnit(1),*)'ERROR in definition of the spatial'//& & ' boundary Conditions:' write(logUnit(1),*)'Selected an unknown spatial function: '//& & trim(me%kind) call tem_abort() end select end subroutine load_spatial_predefined ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This subroutine load 3d parabola type variables from LUA file. !! !! Specify `amplitude` to size of nComp in spatial block. !! If amplitude is not defined, it set to 1.0_rk for all components !! Valid definition: !! !! 1. 2D parabola !!```lua !! spatial = {predefined='parabol', shape = { center/origin={-5.0, 0.0, 0.0}, !! vec={0.0, 1.0, 0.0}}, !! amplitude = 0.01} !! where, center - line center. !! origin - line origin. (define either center or origin) !! vec - length of the line. !!``` !! Parabolic 2D profile at channel inlet. !! !! ![parabol2d](|media|/parabol2d.png) !! !! 2. 3D parabola !!```lua !! spatial = { !! predefined = 'parabol', !! shape = { !! center/origin = {-5.0, 0.0, 0.0}, !! vec = { !! {0.0, 1.0, 0.0}, !! {1.0, 0.0, 0.0} !! }, !! amplitude = 0.01 !! } !! where, center - plane center. !! origin - plane origin. (define either center or origin) !! vec - length of the plane in 2 direction. !! amplitude - maximum value !!``` !! Parabolic 3D profile at channel inlet. !! ![parabol3d](|media|/parabolic3d.png) !! !! Example: !! Inlet velocity at inlet plane with velocity along x-dir with a maximum !! velocity 0.08. !! Inlet plane is normal to x-dir and located at offset of {-5,0,0} from !! origin. The plane spans -1 to 1 in both y and z-dir. !! !!```lua !! boundary_condition = { !! { !! label = 'inlet', !! kind = 'inlet_ubb', !! velocityX = { !! kind = 'combined', !! spatial = { !! predefined='parabol', !! shape = { !! origin = {-5.0, 0.0, 0.0}, !! vec={ {0.0, 1.0, 0.0}, {0.0, 0.0, 1.0} } !! }, !! amplitude = 0.01 !! } !! }, !! velocityY = 0.0 !! velocityZ = 0.0 !! } !! } !!``` !!``` !! _______vecB____ !! | | | !! | | | !! | |______|vecA !! | center | !! | | !! |______________|_ !!``` !! subroutine load_spatial_parabol( me, conf, thandle, nComp ) ! -------------------------------------------------------------------- ! !> parabola3d spatial datas type(spatial_parabol_type),intent(out) :: me !> lua state type type(flu_State) :: conf !> aotus parent handle integer, intent(in) :: thandle !> Number of components integer, intent(in) :: nComp ! -------------------------------------------------------------------- ! integer :: iError ! -------------------------------------------------------------------- ! ! load geometry call tem_load_shape( conf = conf, & & parent = thandle, & & me = me%geometry ) if (size(me%geometry%canoND) /= 1) then write(logUnit(1),*) 'Error: Requires single shape for spatial "parabol"' call tem_abort() end if call load_spatial_asConst( const = me%amplitude, & & conf = conf, & & errCode = iError, & & parent = thandle, & & key = 'amplitude', & & nComp = nComp ) if ( iError /= 0 ) then write(logUnit(1),*) 'Warning: amplitude is not defined.' write(logUnit(1),*) ' Set to default value 1.0 for all components' me%amplitude = ref_amp end if if (nComp == 1) then write(logUnit(5),"(A)") ' amplitude = ' & & // trim(tem_toStr(me%amplitude(1))) else write(logUnit(5),"(A)") ' amplitude = ' & & // trim(tem_toStr(me%amplitude(1:nComp),',')) end if end subroutine load_spatial_parabol ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> Reading the definition for a random distribution function. !! !! This spatial function will return random numbers within a given interval. !! The interval has to be specified by 'min' and 'max' in the Lua !! configuration. !! Resulting values will be given by: min + (max-min)*random_number !! The range defaults to min=0.0 - max=1.0. !! subroutine load_spatial_random( me, conf, thandle ) ! -------------------------------------------------------------------- ! !> random spatial specification type(spatial_random_type),intent(out) :: me !> lua state type type(flu_State) :: conf !> aotus parent handle integer, intent(in) :: thandle ! -------------------------------------------------------------------- ! integer :: iError ! -------------------------------------------------------------------- ! ! val_min call aot_get_val( L = conf, & & thandle = thandle, & & key = 'min', & & val = me%val_min, & & ErrCode = iError, & & default = 0.0_rk ) if ( btest( iError, aoterr_Fatal ) ) then write(logUnit(1),*) 'FATAL Error occured in definition of the spatial' & & // ' function' write(logUnit(1),*) 'while retrieving the min for random numbers!' call tem_abort() end if if( btest( iError, aoterr_NonExistent ))then write(logUnit(1),*) ' WARNING: min is non-existent.' & & // ' Using default value 0.0.' end if write(logUnit(1),*) ' * val_min =', me%val_min ! val_max call aot_get_val( L = conf, & & thandle = thandle, & & key = 'max', & & val = me%val_max, & & ErrCode = iError, & & default = 1.0_rk ) if( btest( iError, aoterr_Fatal ))then write(logUnit(1),*) 'FATAL Error occured in definition of the spatial' & & // ' function' write(logUnit(1),*) 'while retrieving the max for random numbers!' call tem_abort() end if if( btest( iError, aoterr_NonExistent ))then write(logUnit(1),*) ' WARNING: max is non-existent.' & & // ' Using default value 1.0.' end if write(logUnit(1),*) ' * val_max =', me%val_max me%val_range = me%val_max - me%val_min end subroutine load_spatial_random ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function computes 3d parabola profile from treeIDs of an element. !! !! This profile is defined !! by element barycentric coordinate and 3d parabola parameters. !! 3D parabola profile at given plane is computed in the following way: !! !! - Project barycentric coordinate vector in a given plane via !! \( \alpha = ((baryCoord - center) \cdot vecA)/\sqrt{ vecA\cdot vecA }\) !! - Compute spatial value using !! \( res = (1+\alpha)*(1-\alpha)*(1+\beta)*(1-\beta) \) !! Example: !! Parabolic 3D profile at channel inlet. !! !! ![parabolic3d](|media|/parabolic3D.png) !! function tem_spatial_parabol3d_for_treeIds( me, treeIds, tree, n ) result(res) ! -------------------------------------------------------------------- ! !> contains plane parameter for 3d parabola type( tem_canonicalND_type ) :: me !> global treelm mesh type( treelmesh_type ), intent(in) ::tree !> number of return values integer, intent(in) :: n !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> return value of a function real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! real(kind=rk) :: coord(3), alpha, beta, diff(3) real(kind=rk) :: vecAsqr, vecBsqr real(kind=rk) :: center(3), halfvec(2,3) !loop variables integer :: iDir, jDir ! -------------------------------------------------------------------- ! jDir = 0 do iDir = 1, 3 if( me%active( iDir )) then jDir = jDir + 1 halfvec( jDir, : ) = me%vec( :, iDir ) / 2._rk end if end do center = me%origin + halfvec(1, :) + halfvec(2, :) vecAsqr = dot_product( halfvec(1, :), halfvec(1, :) ) vecBsqr = dot_product( halfvec(2, :), halfvec(2, :) ) !loop over number of return values do iDir = 1, n !barycentric coordinate coord = tem_BaryOfId( tree, treeIds(iDir) ) !distance between parabola center and barycentric coordinates diff = coord - center !projection of diff in a plane on vecA alpha = dot_product( diff, halfvec(1, :) ) / vecAsqr !projection of diff in a plane on vecB beta = dot_product( diff, halfvec(2, :) ) / vecBsqr res( iDir ) = ( 1.0_rk-alpha ) * ( 1.0_rk+alpha ) & & * ( 1.0_rk-beta ) * ( 1.0_rk+beta ) if ( abs(alpha) .gt. 1.0_rk .or. abs(beta) .gt. 1.0_rk ) then res( iDir ) = 0.0_rk end if end do end function tem_spatial_parabol3d_for_treeIds ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function computes 3d parabola profile from coord of an element. !! !! This profile is defined !! by element barycentric coordinate and 3d parabola parameters. !! 3D parabola profile at given plane is computed in the following way: !! !! - Project barycentric coordinate vector in a given plane via !! \( \alpha = ((baryCoord - center) \cdot vecA)/\sqrt{ vecA\cdot vecA }\) !! - Compute spatial value using !! \( res = (1+\alpha)*(1-\alpha)*(1+\beta)*(1-\beta) \) !! Example: !! Parabolic 3D profile at channel inlet. !! ![parabolic 3D](|media|/parabolic3D.png) !! !! @todo use projection of point on line and point on plane !! function tem_spatial_parabol3d_for_coord( me, coord, n ) result(res) ! -------------------------------------------------------------------- ! !> contains parameter for 3d parabola type( tem_canonicalND_type ) :: me !> the number of return values integer, intent(in) :: n !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> return value of a function real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! real(kind=rk) :: alpha, beta, diff(3) real(kind=rk) :: vecAsqr, vecBsqr real(kind=rk) :: center(3), halfvec(2,3) integer :: iDir, jDir ! -------------------------------------------------------------------- ! jDir = 0 do iDir = 1, 3 if( me%active( iDir )) then jDir = jDir + 1 halfvec(jDir, :) = me%vec(:, iDir) / 2._rk end if end do center = me%origin + halfvec(1, :) + halfvec(2, :) vecAsqr = dot_product( halfvec(1, :), halfvec(1, :) ) vecBsqr = dot_product( halfvec(2, :), halfvec(2, :) ) !loop over number of return values do iDir = 1, n !distance between parabola center and barycentric coordinates diff = coord(iDir,:) - center !projection of diff in a plane on vecA alpha = dot_product( diff, halfvec(1, :) ) / vecAsqr ! projection of diff in a plane on vecB beta = dot_product( diff, halfvec(2, :) ) / vecBsqr res(iDir) = (1.0_rk - alpha) * (1.0_rk + alpha) & & * (1.0_rk - beta) * (1.0_rk + beta) if ( (abs(alpha) .gt. 1.d0) .or. (abs(beta) .gt. 1.d0) ) then res(iDir) = 0.0_rk end if end do end function tem_spatial_parabol3d_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function computes 2d parabola profile from treeIds of elements !! !! This profile is defined !! by element barycentric coordinate and 2d parabola parameters. !! 2D parabola profile at given plane is computed in the following way: !! !! - Project barycentric coordinate vector in a given plane via !! \( alpha = ((baryCoord - center) \cdot vecA)/\sqrt(vecA\cdot vecA)\) !! - Compute spatial value using !! \( res = (1+alpha)*(1-alpha) \) !! Actual parabola 2d formula: \f$ (y-y_0) = a(x-x_0)^2 \) !! parabola open towards opposite x and with vertex at (1,0) is given by !! \( y = (1-x)^2 \) !! function tem_spatial_parabol2d_for_treeIds( me, treeIds, tree, n ) result(res) ! -------------------------------------------------------------------- ! !> contains parameters for 2d parabola type( tem_canonicalND_type ) :: me !> global treelm mesh type( treelmesh_type ), intent(in) ::tree !> number of return values integer, intent(in) :: n !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> return value of a function real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! real(kind=rk) :: coord(3), alpha, diff(3) real(kind=rk) :: vecAsqr, center(3), halfdir(3) !loop variables integer :: iDir ! -------------------------------------------------------------------- ! ! since this is a line only one of the three vectors in vec ! is active halfdir = 0.0_rk do iDir = 1, 3 if( me%active( iDir )) halfdir = me%vec( :, iDir )/2.0_rk end do center = me%origin + halfdir vecAsqr = dot_product( halfdir, halfdir ) !loop over number of return values do iDir = 1, n !barycentric coordinate coord = tem_BaryOfId( tree, treeIds(iDir) ) !distance between parabola center and barycentric coordinates diff = coord - center !projection of diff in a plane on vecA alpha = dot_product( diff, halfdir ) / vecAsqr res(iDir) = ( 1.0_rk-alpha ) * ( 1.0_rk+alpha ) if ( abs(alpha) .gt. 1.0d0 ) then res(iDir) = 0.0_rk end if end do end function tem_spatial_parabol2d_for_treeIds ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function computes 2d parabola profile from coord of elements !! !! This profile is defined !! by element barycentric coordinate and 2d parabola parameters. !! 2D parabola profile at given plane is computed in the following way: !! !! - Project barycentric coordinate vector in a given plane via !! \( alpha = ((baryCoord - center) \cdot vecA)/\sqrt(vecA\cdot vecA)\) !! - Compute spatial value using !! \( res = (1+alpha)*(1-alpha) \) !! function tem_spatial_parabol2d_for_coord( me, coord, n ) result(res) ! -------------------------------------------------------------------- ! !> contains line parameters for 2d parabola type( tem_canonicalND_type ) :: me !> number of return values integer, intent(in) :: n !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> return value of a function real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! real(kind=rk) :: alpha, diff(3) real(kind=rk) :: vecAsqr, center(3), halfdir(3) ! loop variable integer :: iDir ! -------------------------------------------------------------------- ! halfdir = 0.0_rk do iDir = 1, 3 if( me%active(iDir) ) halfdir = me%vec(:, iDir)/2.0_rk end do vecAsqr = dot_product(halfdir, halfdir) center = me%origin + halfdir !loop over number of return values do iDir = 1, n !distance between parabola center and barycentric coordinates diff = coord(iDir,:) - center !projection of diff in a plane on vecA alpha = dot_product( diff, halfdir ) / vecAsqr res(iDir) = (1.0_rk - alpha) * (1.0_rk + alpha) if ( abs(alpha) .gt. 1.0d0 ) then res(iDir) = 0.0_rk end if end do end function tem_spatial_parabol2d_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> Produce random numbers !! function tem_spatial_random_for( me, n ) result(res) ! -------------------------------------------------------------------- ! !> Interval definition to get the random values from. type(spatial_random_type), intent(in) :: me !> number of return values integer, intent(in) :: n !> return value of a function real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! call random_number(res) res = me%val_min + me%val_range*res end function tem_spatial_random_for ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the Lua function, !! in which the barycentric coordinates are computed from treeIds of an !! element. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) function tem_spatial_lua_for_treeIds( fun_ref, conf, treeIds, tree, n ) & & result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> global treelm mesh type( treelmesh_type ), intent(in) ::tree !> number of return values integer, intent(in) :: n !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> lua state type(flu_State) :: conf !> return value real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError integer :: iDir, jDir real(kind=rk) :: coord(3) ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir=1,n coord = tem_BaryOfId( tree, treeIds(iDir) ) do jDir=1,3 call aot_fun_put(L=conf, fun=fun, arg=coord(jDir)) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir), ErrCode=iError) if ( btest(iError,aoterr_Fatal) ) then write(logunit(0),*) "ERROR Obtaining a spatial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: 1' write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_for_treeIds ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the vectorial Lua function, !! in which the barycentric coordinates are computed from treeIds of an !! element. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) function tem_spatial_lua_vector_for_treeIds( fun_ref, conf, treeIds, tree, & & n, ncomp ) result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> global treelm mesh type(treelmesh_type), intent(in) ::tree !> number of return values integer, intent(in) :: n !> Number of components in each returned value integer, intent(in) :: ncomp !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> lua state type(flu_State) :: conf !> return value real(kind=rk) :: res(n,ncomp) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError(nComp) integer :: iDir, jDir real(kind=rk) :: coord(3) ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir=1,n coord = tem_BaryOfId( tree, treeIds(iDir) ) do jDir=1,3 call aot_fun_put(L=conf, fun=fun, arg=coord(jDir)) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir,:), ErrCode=iError) if ( any(btest(iError,aoterr_Fatal)) ) then write(logunit(0),*) "ERROR Obtaining a spatial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: ', nComp write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_vector_for_treeIds ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the Lua function, !! which takes barycentric coordinates of an element. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) !! function tem_spatial_lua_for_coord( fun_ref, conf, coord, n ) result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> number of return values integer, intent(in) :: n !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> lua state type(flu_State) :: conf !> return value real(kind=rk) :: res(n) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError integer :: iDir, jDir ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir = 1, n do jDir = 1, 3 call aot_fun_put( L=conf, fun=fun, arg=coord(iDir,jDir) ) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir), ErrCode=iError) if ( btest(iError,aoterr_Fatal) ) then write(logunit(0),*) "ERROR Obtaining a spatial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: 1' write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the vectorial Lua function, !! which takes barycentric coordinates of an element. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) !! function tem_spatial_lua_vector_for_coord( fun_ref, conf, coord, n, ncomp ) & & result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> number of return values integer, intent(in) :: n !> number of components in the resulting vector integer, intent(in) :: ncomp !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> lua state type(flu_State), optional :: conf !> return value real(kind=rk) :: res(n,ncomp) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError(ncomp) integer :: iDir, jDir ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir = 1, n do jDir = 1, 3 call aot_fun_put( L=conf, fun=fun, arg=coord(iDir,jDir) ) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir,:), ErrCode=iError) if ( any(btest(iError,aoterr_Fatal)) ) then write(logunit(0),*) "ERROR Obtaining a spactial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: ', nComp write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_vector_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the Lua function, !! which takes tem_grwPoints_type and evaluate a function at a point of !! given idx in grwPnt. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) !! function tem_spatial_lua_for_index( fun_ref, conf, grwPnt, idx, nVals ) & & result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> number of return values integer, intent(in) :: nVals !> growing array of all spatial point of a variable type(tem_grwPoints_type), intent(in) :: grwPnt !> Index position to return a pre-store value or to compute integer, intent(in) :: idx(nVals) !> lua state type(flu_State) :: conf !> return value real(kind=rk) :: res(nVals) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError integer :: iDir, jDir real(kind=rk) :: coord(3) ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir = 1, nVals coord(:) = (/ grwPnt%coordX%val( idx(iDir) ), & & grwPnt%coordY%val( idx(iDir) ), & & grwPnt%coordZ%val( idx(iDir) ) /) do jDir = 1, 3 call aot_fun_put( L=conf, fun=fun, arg=coord(jDir) ) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir), ErrCode=iError) if ( btest(iError,aoterr_Fatal) ) then write(logunit(0),*) "ERROR Obtaining a spatial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: 1' write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_for_index ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes the vectorial Lua function, !! which takes tem_grwPoints_type and evaluate a function at a point of !! given idx in grwPnt. !! !! Lua function defined in the script is !! connected to the conf handle and return the result of the function. !! The Lua function takes barycentric coordinate as input argument !! i.e fun_name(x,y,z) !! function tem_spatial_lua_vector_for_index( fun_ref, conf, grwPnt, idx, & & nVals, nComps ) result(res) ! -------------------------------------------------------------------- ! !> Lua reference to the function to evaluate. integer, intent(in) :: fun_ref !> number of return values integer, intent(in) :: nVals !> number of components per returned value integer, intent(in) :: nComps !> growing array of all spatial point of a variable type(tem_grwPoints_type), intent(in) :: grwPnt !> Index position to return a pre-store value or to compute integer, intent(in) :: idx(nVals) !> lua state type(flu_State) :: conf !> return value real(kind=rk) :: res(nVals,nComps) ! -------------------------------------------------------------------- ! type(aot_fun_type) :: fun integer :: iError(ncomps) integer :: iDir, jDir real(kind=rk) :: coord(3) ! -------------------------------------------------------------------- ! call aot_fun_open(L=conf, fun=fun, ref=fun_ref) do iDir = 1, nVals coord(:) = (/ grwPnt%coordX%val( idx(iDir) ), & & grwPnt%coordY%val( idx(iDir) ), & & grwPnt%coordZ%val( idx(iDir) ) /) do jDir = 1, 3 call aot_fun_put( L=conf, fun=fun, arg=coord(jDir) ) end do call aot_fun_do(L=conf, fun=fun, nresults=1) call aot_top_get_val(L=conf, val=res(iDir,:), ErrCode=iError) if ( any(btest(iError,aoterr_Fatal)) ) then write(logunit(0),*) "ERROR Obtaining a spactial function" write(logunit(0),*) "Probably wrong number of components returned" write(logunit(0),*) "or a scalar was return as a lua table" write(logunit(0),*) 'Expected nComp: ', nComps write(logunit(0),*) 'ErrorCodes: ', iError write(logunit(0),*) "Check return values of your Lua functions!" call tem_abort() end if end do call aot_fun_close(L=conf, fun=fun) end function tem_spatial_lua_vector_for_index ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes different spatial boundary kinds like constant, lua !! function or predefined Fortran function for given treeIDs !! !! If a spatial block is not defined, default value is set to 1.0 !! or default value passed while loading tem_load_spatial. !! If both spatial and temporal block are not defined in the lua file, the !! return value = 1.0_rk. !! based spatial_kind(kind). !! !! 1. const - set constant value !! 2. lua_fun - lua function !! 3. gausspulse - fortran gauss pulse function !! 4. 2dcrvp - fortran spinning vortex function !! 5. parabol - fotran parabolic function !! function tem_spatial_for_treeIDs( me, treeIds, tree, n) result( res ) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type( tem_spatial_type ) :: me !> global treelm mesh type( treelmesh_type ), intent(in) ::tree !> number of return values integer, intent(in) :: n !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> return value of a function real( kind=rk ) :: res(n) ! -------------------------------------------------------------------- ! select case( trim(adjustl(me%kind)) ) case( 'none', 'const' ) res = me%const(1) case( 'lua_fun' ) res = tem_spatial_lua_for( me%lua_fun_ref, me%conf, treeIds, tree, n) case( 'parabol' ) select case( trim(adjustl(me%parabol%geometry%canoND(1)%kind)) ) case('line') res = tem_spatial_parabol2d_for( me%parabol%geometry%canoND(1), & & treeIds, & & tree, & & n ) case('plane') res = tem_spatial_parabol3d_for( me%parabol%geometry%canoND(1), & & treeIds, & & tree, & & n ) end select res = res*me%parabol%amplitude(1) case ('random') res = tem_spatial_random_for(me%random, n) case( 'spongelayer_plane', 'spongelayer_plane_2d', 'spongelayer_plane_1d' ) res = tem_spongeLayer_plane_for(me%spongePlane, treeids, tree, n) case( 'spongelayer_box' ) res = tem_spongeLayer_box_for(me%spongeBox, treeids, tree, n) case( 'spongelayer_box_2d' ) res = tem_spongeLayer_box2d_for(me%spongeBox, treeids, tree, n) case( 'spongelayer_radial_2d') res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 2 ) case( 'spongelayer_radial') res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 3 ) case( 'viscous_spongelayer_plane' ) res = tem_viscSpongeLayer_plane_for(me%spongePlane, treeids, tree, n) case( 'viscous_spongelayer_box' ) res = tem_viscSpongeLayer_box_for(me%spongeBox, treeids, tree, n) case( 'viscous_spongelayer_box_2d' ) res = tem_viscSpongeLayer_box2d_for(me%spongeBox, treeids, tree, n) case( 'viscous_spongelayer_radial_2d') res = tem_viscSpongeLayer_radial_for( & & me = me%spongeRadial, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 2 ) case( 'viscous_spongelayer_radial') res = tem_viscSpongeLayer_radial_for( & & me = me%spongeRadial, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 3 ) case default call tem_abort( & & 'ERROR: Unknown spatial function in tem_spatial_for_treeIDs.' ) end select end function tem_spatial_for_treeIDs ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! function tem_spatial_vector_for_treeIDs( me, treeIds, tree, n, ncomp) & & result(res) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type(tem_spatial_type) :: me !> global treelm mesh type(treelmesh_type), intent(in) ::tree !> number of return values integer, intent(in) :: n !> number of components in the resulting vector integer, intent(in) :: ncomp !> treeIds of elements in given level integer(kind=long_k), intent(in) :: treeIds(n) !> return value of a function real(kind=rk) :: res(n,ncomp) ! -------------------------------------------------------------------- ! integer :: i ! -------------------------------------------------------------------- ! select case( trim(adjustl(me%kind)) ) case( 'none', 'const' ) do i = 1, nComp res(:,i) = me%const(i) end do case( 'lua_fun' ) res = tem_spatial_lua_for( fun_ref = me%lua_fun_ref, & & conf = me%conf, & & treeIds = treeIds, & & tree = tree, & & n = n, & & ncomp = ncomp ) case( 'spongelayer_plane', 'spongelayer_plane_2d', 'spongelayer_plane_1d' ) res = tem_spongeLayer_plane_for(me%spongePlane, nComp, treeids, tree, n) case( 'spongelayer_box' ) res = tem_spongeLayer_box_for(me%spongeBox, nComp, treeids, tree, n) case( 'spongelayer_box_2d' ) res = tem_spongeLayer_box2d_for(me%spongeBox, nComp, treeids, tree, n) case( 'spongelayer_radial_2d') res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 2 ) case( 'spongelayer_radial') res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & treeids = treeids, & & tree = tree, & & n = n, & & nDim = 3 ) case( 'parabol' ) select case( trim(adjustl(me%parabol%geometry%canoND(1)%kind)) ) case('line') res(:,1) = tem_spatial_parabol2d_for( & & me = me%parabol%geometry%canoND(1), & & treeIds = treeIds, & & tree = tree, & & n = n ) case('plane') res(:,1) = tem_spatial_parabol3d_for( & & me = me%parabol%geometry%canoND(1), & & treeIds = treeIds, & & tree = tree, & & n = n ) end select do i = 2, nComp res(:,i) = res(:,1)*me%parabol%amplitude(i) end do res(:,1) = res(:,1)*me%parabol%amplitude(1) case default write(logUnit(1),*)'ERROR: No vectorial routine for spatial functions of' write(logUnit(1),*)' kind "' // trim(adjustl(me%kind)) // '"' write(logUnit(1),*)' available! Have a look in the ' & & // 'tem_spatial_module' write(logUnit(1),*)' for implemented vectorial functions.' call tem_abort() end select end function tem_spatial_vector_for_treeIDs ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes different spatial boundary kinds like constant, lua !! function or predefined Fortran function for given coord !! !! If a spatial block is not defined and a temporal block is defined in the !! lua file, the return value is either 1.0 or default value provided !! in tem_load_spatial. !! If both spatial and temporal block are not defined in the lua file, the !! return value = 1.0_rk. !! based spatial_kind(kind). !! !! 1. const - set constant value !! 2. lua_fun - lua function !! 3. gausspulse - fortran gauss pulse function !! 4. 2dcrvp - fortran spinning vortex function !! 5. parabol - fotran parabolic function !! function tem_spatial_for_coord( me, coord, n ) result( res ) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type(tem_spatial_type), intent(in) :: me !> number of return values integer, intent(in) :: n !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> return value of a function real( kind=rk ) :: res(n) ! -------------------------------------------------------------------- ! select case( trim(adjustl(me%kind)) ) case( 'none', 'const' ) res = me%const(1) case( 'lua_fun' ) res = tem_spatial_lua_for(me%lua_fun_ref, me%conf, coord, n) case ('random') res = tem_spatial_random_for(me%random, n) case( 'parabol' ) select case( trim(adjustl(me%parabol%geometry%canoND(1)%kind)) ) case('line') res = tem_spatial_parabol2d_for( & & me = me%parabol%geometry%canoND(1), & & coord = coord, & & n = n ) case('plane') res = tem_spatial_parabol3d_for( & & me = me%parabol%geometry%canoND(1), & & coord = coord, & & n = n ) end select res = res*me%parabol%amplitude(1) case( 'viscous_spongelayer_plane' ) res = tem_viscSpongelayer_plane_for( & & me = me%spongePlane, & & coord = coord, & & n = n ) case( 'viscous_spongelayer_box' ) res = tem_viscSpongelayer_box_for( & & me = me%spongeBox, & & coord = coord, & & n = n ) case( 'viscous_spongelayer_box_2d' ) res = tem_viscSpongelayer_box2d_for( & & me = me%spongeBox, & & coord = coord, & & n = n ) case( 'viscous_spongelayer_radial_2d' ) res = tem_viscSpongelayer_radial_for( & & me = me%spongeRadial, & & coord = coord, & & nDim = 2, & & n = n ) case( 'viscous_spongelayer_radial' ) res = tem_viscSpongelayer_radial_for( & & me = me%spongeRadial, & & coord = coord, & & nDim = 3, & & n = n ) case( 'gausspulse' ) res = ic_gausspulse_for(me%gausspulse, coord, n) case( 'crvpX' ) res = ic_2dcrvpX_for(me%crvp, coord, n) case( 'crvpY' ) res = ic_2dcrvpY_for(me%crvp, coord, n) case( 'crvpPressure' ) res = ic_2dcrvpPressure_for(me%crvp, coord, n) case('miescatter_displacementfieldz') res = tem_eval_miescatter_displz( me = me%mie_fun, & & coord = coord, & & time = 0.0_rk, & & n = n ) case('miescatter_magneticfieldx') res = tem_eval_miescatter_magnx( me = me%mie_fun, & & coord = coord, & & time = 0.0_rk, & & n = n ) case('miescatter_magneticfieldy') res = tem_eval_miescatter_magny( me = me%mie_fun, & & coord = coord, & & time = 0.0_rk, & & n = n ) case('heaviside_gibbs') res = tem_eval_heaviside_gibbs( me = me%heaviside_gibbs_fun, & & coord = coord, & & n = n ) case('cylindricalwave') res = tem_eval_cylindricalWave( me = me%cylindricalWave, & & coord = coord, & & time = 0.0_rk, & & n = n ) case('tgv_p') res = ic_tgv_pressure_for( me%tgv, coord, n ) case('tgv_ux') res = ic_tgv_ux_for( me%tgv, coord, n ) case('tgv_uy') res = ic_tgv_uy_for( me%tgv, coord, n ) case('tgv_sxx') res = ic_tgv_sxx_for( me%tgv, coord, n ) case('tgv_syy') res = ic_tgv_syy_for( me%tgv, coord, n ) case('tgv_sxz') res = ic_tgv_sxz_for( me%tgv, coord, n ) case('tgv_syz') res = ic_tgv_syz_for( me%tgv, coord, n ) case('polygon_material') res = tem_eval_polygon_material_scal( me = me%polygon_material, & & coord = coord, & & n = n ) case('polygon_material_3d') res = tem_eval_polygon_material_scal_3d( me = me%polygon_material, & & coord = coord, & & n = n ) case( 'spongelayer_plane', 'spongelayer_plane_2d', 'spongelayer_plane_1d' ) res = tem_spongeLayer_plane_for(me%spongePlane, coord, n) case( 'spongelayer_box' ) res = tem_spongeLayer_box_for(me%spongeBox, coord, n) case( 'spongelayer_box_2d' ) res = tem_spongeLayer_box2d_for(me%spongeBox, coord, n) case( 'spongelayer_radial_2d' ) res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & coord = coord, & & n = n, & & nDim = 2 ) case( 'spongelayer_radial' ) res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & coord = coord, & & n = n, & & nDim = 3 ) case default call tem_abort( & & 'ERROR: Unknown spatial function in tem_spatial_for_coord.' ) end select end function tem_spatial_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function invokes different spatial boundary kinds like constant, lua !! function or predefined Fortran function for given coord !! !! If a spatial block is not defined and a temporal block is defined in the !! lua file, the return value = ref_value. !! If both spatial and temporal block are not defined in the lua file, the !! return value = 1.0_rk. !! based spatial_kind(kind). !! !! 1. const - set constant value !! 2. lua_fun - lua function !! 3. gausspulse - fortran gauss pulse function !! 4. 2dcrvp - fortran spinning vortex function !! 5. parabol - fotran parabolic function function tem_spatial_vector_for_coord( me, coord, n, ncomp ) result( res ) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type(tem_spatial_type) :: me !> number of return values integer, intent(in) :: n !> number of components per returned value integer, intent(in) :: ncomp !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(n,3) !> return value of a function real( kind=rk ) :: res(n,ncomp) ! -------------------------------------------------------------------- ! integer :: i ! -------------------------------------------------------------------- ! select case( trim(adjustl(me%kind)) ) case( 'none', 'const' ) do i = 1, nComp res(:,i) = me%const(i) end do case( 'lua_fun' ) res = tem_spatial_lua_for(me%lua_fun_ref, me%conf, coord, n, ncomp) case( 'spongelayer_plane', 'spongelayer_plane_2d', 'spongelayer_plane_1d' ) res = tem_spongeLayer_plane_for(me%spongePlane, nComp, coord, n) case( 'spongeLayer_box' ) res = tem_spongeLayer_box_for(me%spongeBox, nComp, coord, n) case( 'spongeLayer_box_2d' ) res = tem_spongeLayer_box2d_for(me%spongeBox, nComp, coord, n) case( 'spongelayer_radial_2d' ) res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & coord = coord, & & n = n, & & nDim = 2 ) case( 'spongelayer_radial' ) res = tem_spongeLayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & coord = coord, & & n = n, & & nDim = 3 ) case( 'radial_spongelayer_2d' ) res = tem_spongelayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & coord = coord, & & nDim = 2, & & n = n ) case( 'radial_spongelayer' ) res = tem_spongelayer_radial_for( & & me = me%spongeRadial, & & nComp = nComp, & & coord = coord, & & nDim = 3, & & n = n ) case( 'pml' ) res = tem_evaluate_pml(me%pml, nComp, coord, n) case( 'polygon_material' ) res = tem_eval_polygon_material( me = me%polygon_material, & & coord = coord, & & n = n ) case( 'polygon_material_3d' ) res = tem_eval_polygon_material_3d( me = me%polygon_material, & & coord = coord, & & n = n ) case( 'parabol' ) select case( trim(adjustl(me%parabol%geometry%canoND(1)%kind)) ) case( 'line' ) res(:,1) = tem_spatial_parabol2d_for( & & me = me%parabol%geometry%canoND(1), & & coord = coord, & & n = n ) case( 'plane' ) res(:,1) = tem_spatial_parabol3d_for( & & me = me%parabol%geometry%canoND(1), & & coord = coord, & & n = n ) end select do i = 2, nComp res(:,i) = res(:,1)*me%parabol%amplitude(i) end do res(:,1) = res(:,1)*me%parabol%amplitude(1) case('rectangular', 'gate') do i = 1, n if( (abs(coord(i,2)) < me%rect_ly) & & .and. (abs(coord(i,3)) < me%rect_lz) ) then res(i,1) = 1.0_rk else res(i,1) = 0.0_rk end if end do res(:, 2:nComp) = 0.0_rk case default write(logUnit(1),*)'ERROR: No vectorial routine for spatial functions of' write(logUnit(1),*)' kind "' // trim(adjustl(me%kind)) // '"' write(logUnit(1),*)' available! Have a look in the ' & & // 'tem_spatial_module' write(logUnit(1),*)' for implemented vectorial functions.' call tem_abort() end select end function tem_spatial_vector_for_coord ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function returns pre-stored value at given idx or evaluate a spatial !! function for a point at given idx in growing array of points. !! Return value is a scalar. function tem_spatial_scalar_for_index( me, grwPnt, idx, nVals, iLevel ) & & result (res) ! -------------------------------------------------------------------- ! !> spatial type type(tem_spatial_type), intent(in) :: me !> number of return values integer, intent(in) :: nVals !> growing array of all spatial point of a variable type(tem_grwPoints_type), intent(in) :: grwPnt !> Index position to return a pre-store value or to compute integer, intent(in) :: idx(nVals) !> return value of a function real( kind=rk ) :: res(nVals) !> Level to which the evaluated values to be returned integer, intent(in) :: iLevel ! -------------------------------------------------------------------- ! integer :: iVal real(kind=rk) :: coord(1,3), res_tmp(1) ! -------------------------------------------------------------------- ! if (me%isStored) then res(1:nVals) = me%valOnLvl(iLevel)%evalVal%val( idx(1:nVals) ) else select case (trim(me%kind)) case ('none', 'const') res = me%const(1) case ('lua_fun') res = tem_spatial_lua_for( fun_ref = me%lua_fun_ref, & & conf = me%conf, & & grwPnt = grwPnt, & & idx = idx, & & nVals = nVals ) case default do iVal = 1, nVals coord(1,:) = (/ grwPnt%coordX%val( idx(iVal) ), & & grwPnt%coordY%val( idx(iVal) ), & & grwPnt%coordZ%val( idx(iVal) ) /) res_tmp = tem_spatial_for_coord( me = me, & & coord = coord, & & n = 1 ) res(iVal) = res_tmp(1) end do end select end if end function tem_spatial_scalar_for_index ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This function returns pre-stored value at given idx or evaluate a spatial !! function for a point at given idx. !! Return value is a vector. function tem_spatial_vector_for_index( me, grwPnt, idx, nVals, iLevel, & & nComps ) result (res) ! -------------------------------------------------------------------- ! !> spatial type type(tem_spatial_type), intent(in) :: me !> number of return values integer, intent(in) :: nVals !> number of components per returned value integer, intent(in) :: nComps !> growing array of all spatial point of a variable type(tem_grwPoints_type), intent(in) :: grwPnt !> Index position to return a pre-store value or to compute integer, intent(in) :: idx(nVals) !> return value of a function real( kind=rk ) :: res(nVals, nComps) !> Level to which the evaluated values to be returned integer, intent(in) :: iLevel ! -------------------------------------------------------------------- ! integer :: iVal, iComp, offset real(kind=rk) :: coord(1,3), res_tmp(1, nComps) ! -------------------------------------------------------------------- ! if (me%isStored) then do iVal = 1, nVals offset = (idx(iVal)-1)*nComps res(iVal, :) = me%valOnLvl(iLevel)%evalVal%val( offset+1 & & :offset+nComps ) end do else select case (trim(me%kind)) case ('none', 'const') do iComp = 1, nComps res(:, iComp) = me%const(iComp) end do case ('lua_fun') res = tem_spatial_lua_for( fun_ref = me%lua_fun_ref, & & conf = me%conf, & & grwPnt = grwPnt, & & idx = idx, & & nVals = nVals, & & nComps = nComps ) case default do iVal = 1, nVals coord(1,:) = (/ grwPnt%coordX%val( idx(iVal) ), & & grwPnt%coordY%val( idx(iVal) ), & & grwPnt%coordZ%val( idx(iVal) ) /) res_tmp = tem_spatial_vector_for_coord( me = me, & & coord = coord, & & n = 1, & & nComp = nComps ) res(iVal,:) = res_tmp(1,:) end do end select end if end function tem_spatial_vector_for_index ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This routine evaluate scalar spatial function and store its value in !! growing array subroutine tem_spatial_scalar_storeVal( me, coord, nVals, iLevel ) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type(tem_spatial_type), intent(inout) :: me !> number of return values integer, intent(in) :: nVals !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(nVals,3) !> Level to which the evaluated values to be stored integer, intent(in) :: iLevel ! -------------------------------------------------------------------- ! real(kind=rk) :: evalVal(nVals) ! -------------------------------------------------------------------- ! ! Do not store value for const or none if (trim(me%kind) /= 'const' .or. trim(me%kind) /= 'none') then me%isStored = .true. evalVal = tem_spatial_for( me = me, & & coord = coord, & & n = nVals ) call append( me = me%valOnLvl(iLevel)%evalVal, & & val = evalVal, & & length = nVals ) call truncate(me = me%valOnLvl(iLevel)%evalVal) else me%isStored = .false. end if end subroutine tem_spatial_scalar_storeVal ! ------------------------------------------------------------------------ ! ! ------------------------------------------------------------------------ ! !> This routine evaluate vector spatial function and store its value in !! growing array with access Array Of Structure pattern !! (iVal-1)*nComps + iComp subroutine tem_spatial_vector_storeVal( me, coord, nVals, iLevel, nComps ) ! -------------------------------------------------------------------- ! !> spatial type for given boundary state type(tem_spatial_type), intent(inout) :: me !> number of return values integer, intent(in) :: nVals !> number of components per returned value integer, intent(in) :: nComps !> barycentric Ids of an elements. !! 1st index goes over number of elements and !! 2nd index goes over x,y,z coordinates real(kind=rk), intent(in) :: coord(nVals,3) !> Level to which the evaluated values to be stored integer, intent(in) :: iLevel ! -------------------------------------------------------------------- ! real(kind=rk) :: evalVal(nVals, nComps) integer :: iVal ! -------------------------------------------------------------------- ! ! Do not store value for const or none if (trim(me%kind) /= 'const' .or. trim(me%kind) /= 'none') then me%isStored = .true. evalVal = tem_spatial_for( me = me, & & coord = coord, & & n = nVals, & & nComp = nComps ) ! Append evaluated values in 1D growing array with AOS acces do iVal = 1, nVals call append( me = me%valOnLvl(iLevel)%evalVal, & & val = evalVal(iVal,:), & & length = nVals * nComps ) end do call truncate(me = me%valOnLvl(iLevel)%evalVal) else me%isStored = .false. end if end subroutine tem_spatial_vector_storeVal ! ------------------------------------------------------------------------ ! end module tem_spatial_module