Path: blob/devel/misc/netcdf/src/GridDataMapper/GridDataMapper.f90
3206 views
!------------------------------------------------------------------------------1! Peter RÃ¥back, Vili Forsell2! Created: 7.6.20113! Last Modified: 4.8.20114!------------------------------------------------------------------------------5SUBROUTINE GridDataMapper( Model,Solver,dt,TransientSimulation )6!------------------------------------------------------------------------------7!******************************************************************************8!9! This subroutine saves scalar values to a matrix.10!11! ARGUMENTS:12!13! TYPE(Model_t) :: Model,14! INPUT: All model information (mesh, materials, BCs, etc...)15!16! TYPE(Solver_t) :: Solver17! INPUT: Linear & nonlinear equation solver options18!19! REAL(KIND=dp) :: dt,20! INPUT: Timestep size for time dependent simulations21!22! LOGICAL :: TransientSimulation23! INPUT: Steady state or transient simulation24!25!******************************************************************************2627!******************************************************************************28! Notes: o Performs a modification from measurements with uniform grid into Elmer with an unstructured grid29! o Remember to see if incremental processing might be possible30! o Some terminology: "nodes" and "edges" used for grid points and the lines connecting the for grid points and the lines connecting them31!******************************************************************************3233USE DefUtils, ONLY: dp, Solver_t, Model_t, Mesh_t,GetInteger, CoordinateSystemDimension, GetSolverParams, &34GetLogical, MAX_NAME_LEN, GetCReal35USE Messages, ONLY: Info, Warn, Fatal, Message36USE NetCDF37USE NetCDFGridUtils, ONLY: UniformGrid_t, PrintGrid38USE NetCDFInterpolate, ONLY: Interpolate, LinearInterpolation39USE NetCDFGeneralUtils, ONLY: CloseNetCDF, TimeType_t40USE MapperUtils, ONLY: GetElmerMinMax, GetElmerNodeValue41USE CustomTimeInterpolation, ONLY: ChooseTimeInterpolation4243IMPLICIT NONE4445!------------------------------------------------------------------------------46LOGICAL, PARAMETER :: DEBUG = .FALSE. ! Shows the basic debug info on grids and dimensions47LOGICAL, PARAMETER :: DEBUG_MORE = .FALSE. ! Shows also debug printouts for each iteration48!------------------------------------------------------------------------------49TYPE(Solver_t), TARGET :: Solver50TYPE(Model_t) :: Model51REAL(KIND=dp) :: dt52LOGICAL :: TransientSimulation53!------------------------------------------------------------------------------54! Local variables55!------------------------------------------------------------------------------5657TYPE(Mesh_t), POINTER :: Mesh58TYPE(TimeType_t) :: Time59TYPE(UniformGrid_t) :: Grids(2)60INTEGER :: k, node, DIM, MAX_STEPS61INTEGER, POINTER :: FieldPerm(:)62REAL(KIND=dp), POINTER :: Field(:)63REAL(KIND=dp), ALLOCATABLE :: x(:)64REAL(KIND=dp) :: interp_val, interp_val2, u1(2), u2(2)65INTEGER, ALLOCATABLE :: dim_lens(:) ! Lengths for all dimensions66INTEGER :: NCID, loop, Var_ID, alloc_stat67CHARACTER (len = MAX_NAME_LEN) :: Coord_System, TimeInterpolationMethod68REAL(KIND=dp) :: InterpMultiplier, InterpBias69LOGICAL :: output_on7071!------------------------------------------------------------------------------72! General initializations73!------------------------------------------------------------------------------7475CALL Info('GridDataMapper','-----------------------------------------', Level=4 )76CALL Info('GridDataMapper','Getting field from grid data',Level=4)7778Time % val = -1.0_dp79Time % id = -180Time % len = -181Time % low = -182Time % high = -183Time % doInterpolation = .FALSE.84Time % is_defined = .FALSE.8586! WRITE (*,*) 'val ', Time % val, ' id ', Time % id, ' len ', Time % len,&87! ' low ', Time % low, ' high ', Time % high, ' interp ', Time % doInterpolation8889IF ( TransientSimulation ) THEN90MAX_STEPS = GetInteger( Model % Simulation, 'TimeStep Intervals' )91ELSE92MAX_STEPS = 1 ! Steady state93END IF9495!-- Pointer declarations96Mesh => Solver % Mesh97Field => Solver % Variable % Values ! This vector will get the field values now98FieldPerm => Solver % Variable % Perm99100!------------------------------------------------------------------------------101! Initializing NetCDF values102!------------------------------------------------------------------------------103CALL InitNetCDF(Solver, NCID, Var_ID, dim_lens, Grids, Time, TransientSimulation, dt, MAX_STEPS, Coord_System)104DIM = Grids(1) % COORD_COUNT ! Abbreviation [# of Elmer coordinates .EQ. # of NetCDF coordinates]105106!------------------------------------------------------------------------------107! Initializing Elmer mesh vectors, scaling and interpolation108!------------------------------------------------------------------------------109IF ( DIM .GT. 0 ) THEN110ALLOCATE ( x(DIM), STAT = alloc_stat )111IF ( alloc_stat .NE. 0 ) THEN112CALL Fatal('GridDataMapper','Memory ran out')113END IF114115!--- Scales the Grids, if applicable116CALL InitScaling(Solver, Grids)117END IF118119!------ Debug printouts -------------------------120IF (DEBUG) THEN121IF ( DIM .GT. 0 ) THEN122PRINT *,'Initial Elmer Grid Bounding Box:'123DO loop = 1,DIM,1124PRINT *,'Coordinate ', loop,':', GetElmerMinMax(Solver,loop,.TRUE.), GetElmerMinMax(Solver,loop,.FALSE.)125END DO126END IF127128DO loop = 1,size(Grids,1),1129CALL PrintGrid(Grids(loop),loop)130END DO131END IF132!------------------------------------------------133134!--- Initializes the interpolation variables135CALL InitInterpolation( Solver, DIM, Grids, TimeInterpolationMethod, InterpMultiplier, InterpBias )136137!------------------------------------------------------------------------------138! INTERPOLATION LOOP139!------------------------------------------------------------------------------140! NOTE: Interpolate() effectively ignores time, if "Time % is_defined" is .FALSE.141!------------------------------------------------------------------------------142143output_on = .TRUE. ! If true, outputs some iteration information144! Go through the active nodes and perform interpolation145DO node=1, Mesh % NumberOfNodes146k = FieldPerm(node)147IF( k == 0 ) CYCLE148149IF ( DIM .GT. 0 ) THEN150151! The point of interest152DO loop = 1,DIM,1153x(loop) = GetElmerNodeValue(Solver,node,Grids(1) % Elmer_perm(loop))154END DO155156!--- Perform time interpolation, if needed157IF ( Time % doInterpolation ) THEN ! Two time values (otherwise not interpolated)158IF ( .NOT. (Interpolate(Solver,NCID,Var_ID,dim_lens,Grids(1),&159Time, Time % low,interp_val,Coord_System,x) .AND. Interpolate(Solver,NCID,&160Var_ID,dim_lens,Grids(2),Time,Time % high,interp_val2,Coord_System,x)) ) THEN161CYCLE162ELSE163! Time interpolation on already interpolated space values; save result in interp_val, use original time to weigh164u1(1) = Time % low165u1(2) = interp_val166u2(1) = Time % high167u2(2) = interp_val2168interp_val = ChooseTimeInterpolation(Time % val,u1,u2,TimeInterpolationMethod,output_on) ! Chooses the time interpolation method169! See: CustomTimeInterpolation.f90170output_on = .FALSE.171END IF172ELSE ! Holds: Time % low = Time % high = Time % val, also: Time % IS_DEFINED = .FALSE. works!173IF (.NOT. Interpolate(Solver,NCID,Var_ID,dim_lens,Grids(1),&174Time,Time % low,interp_val,Coord_System,x) ) THEN175CYCLE ! Ignore values for incompatible interpolation176END IF177END IF178ELSE179180!------------------------------------------------------------------------------181! No coordinate dimensions; only time and constant dimensions.182!------------------------------------------------------------------------------183IF ( Time % doInterpolation ) THEN184!--- Time interpolation in effect, perform as before185IF (.NOT. (Interpolate(Solver,NCID,Var_ID,dim_lens,Grids(1),&186Time,Time % low,interp_val,Coord_System) .AND. &187Interpolate(Solver,NCID,Var_ID,dim_lens,Grids(2),&188Time,Time % high,interp_val2,Coord_System)) ) THEN189CYCLE190ELSE191u1(1) = Time % low192u1(2) = interp_val193u2(1) = Time % high194u2(2) = interp_val2195interp_val = ChooseTimeInterpolation(Time % val,u1,u2,TimeInterpolationMethod,output_on)196! See: CustomTimeInterpolation.f90197output_on = .FALSE.198END IF199ELSE200!--- No time interpolation201IF (.NOT. Interpolate(Solver,NCID,Var_ID,dim_lens,Grids(1),&202Time,Time % low,interp_val,Coord_System) ) THEN203CYCLE204END IF205END IF206207END IF208209!------ Debug printouts -------------------------210IF (DEBUG_MORE) THEN211PRINT *,'Interpolation result: ', interp_val212END IF213!------------------------------------------------214215Field(k) = InterpMultiplier*interp_val + InterpBias ! Doesn't modify the result by default216END DO217218!------------------------------------------------------------------------------219! Close the NetCDF file220!------------------------------------------------------------------------------221CALL CloseNetCDF(NCID)222223!------------------------------------------------------------------------------224225CALL Info('GridDataMapper','All done',Level=4)226CALL Info('GridDataMapper', '-----------------------------------------', Level=4 )227228CONTAINS229230!----------------- InitScaling() --------------------231!--- Adds scaling to NetCDF Grids (by default does nothing)232SUBROUTINE InitScaling(Solver, Grids)233!----------------------------------------------------234USE DefUtils, ONLY: Solver_t235USE NetCDFGridUtils, ONLY: UniformGrid_t236USE MapperUtils, ONLY: GetElmerMinMax237IMPLICIT NONE238239!------------------------------------------------------------------------------240! ARGUMENTS241!------------------------------------------------------------------------------242TYPE(Solver_t), INTENT(IN) :: Solver243TYPE(UniformGrid_t), INTENT(INOUT) :: Grids(:)244245!------------------------------------------------------------------------------246! VARIABLES247!------------------------------------------------------------------------------248LOGICAL :: Found, ENABLE_SCALING249INTEGER :: DIM, alloc_stat250REAL(KIND=dp), ALLOCATABLE :: x0e(:), x1e(:)251252!------------------------------------------------------------------------------253! Adds scaling, if it's set on and possible254!------------------------------------------------------------------------------255256ENABLE_SCALING = GetLogical(GetSolverParams(Solver), "Enable Scaling", Found)257DIM = Grids(1) % COORD_COUNT258259IF ( Found .AND. ENABLE_SCALING .AND. DIM .GT. 0 ) THEN260261CALL Warn('GridDataMapper','Elmer grid is scaled to match the NetCDF grid')262263ALLOCATE (x0e(DIM),x1e(DIM), STAT=alloc_stat)264IF ( alloc_stat .NE. 0 ) THEN265CALL Fatal('GridDataMapper','Memory ran out')266END IF267268!--- Collects the range of the Elmer mesh bounding box for scaling269DO loop = 1,DIM,1270x0e(loop) = GetElmerMinMax(Solver,loop,.TRUE.)271x1e(loop) = GetElmerMinMax(Solver,loop,.FALSE.)272END DO273274!--- Scales275DO loop = 1,size(Grids,1),1276! First the scaling to same size (Eq. a( X1E(1)-X0E(1) ) = (X1(1)-X0(1)) ; ranges over a dimension are same. Solved for a, 1 if equal)277Grids(loop) % scale(:) = (Grids(loop) % X1(1:DIM) - Grids(loop) % X0(1:DIM))/(X1E(1:DIM)-X0E(1:DIM)) ! Note: "/" and "*" elementwise operations for arrays in Fortran278! Second the vector to reach X0 from the scaled X0E (wherever it is)279Grids(loop) % move(:) = Grids(loop) % X0(1:DIM) - Grids(loop) % scale(:)*X0E(1:DIM) ! zero, if equal280END DO281END IF282!------------------------------------------------------------------------------283284END SUBROUTINE InitScaling285286!----------------- InitNetCDF() ---------------------287!--- Gathers and initializes all the necessary NetCDF information for picking variables288SUBROUTINE InitNetCDF(Solver, NCID, Var_ID, dim_lens, Grids, Time,&289IS_TRANSIENT, STEP_SIZE, MAX_STEPS, Coord_System )290!--------------------------------------------------291292USE NetCDFGridUtils, ONLY: PrintGrid, InitGrid, GetNetCDFGridParameters, Focus2DNetCDFGrid293USE NetCDFGeneralUtils, ONLY: GetAllDimensions, G_Error, TimeValueToIndex294USE MapperUtils, ONLY: IntWidth, GetNetCDFAccessParameters295USE NetCDF296USE DefUtils, ONLY: dp, MAX_NAME_LEN, GetSolverParams, GetString, GetConstReal, ListGetString297USE Messages, ONLY: Fatal, Message298IMPLICIT NONE299300!------------------------------------------------------------------------------301! ARGUMENTS302!------------------------------------------------------------------------------303TYPE(Solver_t), INTENT(IN) :: Solver ! Elmer solver from SIF304TYPE(TimeType_t), INTENT(INOUT) :: Time ! Time information305TYPE(UniformGrid_t), INTENT(INOUT) :: Grids(:) ! NetCDF grids306LOGICAL, INTENT(IN) :: IS_TRANSIENT ! For using Elmer time instead of a variable307REAL(KIND=dp), INTENT(IN) :: STEP_SIZE ! Time step for Elmer transient system308INTEGER, INTENT(IN) :: MAX_STEPS ! Max steps in Elmer transient system309INTEGER, INTENT(OUT) :: NCID, Var_ID ! NCID is the ID of the opened file, Var_ID the accessed variable id310INTEGER, INTENT(INOUT), ALLOCATABLE :: dim_lens(:) ! Lengths for all dimensions311CHARACTER (len = MAX_NAME_LEN), INTENT(OUT) :: Coord_System ! Coordinate system string312313!------------------------------------------------------------------------------314! NetCDF VARIABLES315!------------------------------------------------------------------------------316317INTEGER :: DIM ! Used Elmer dimensions for data accessing318INTEGER, ALLOCATABLE :: dim_ids(:) ! Ids for all dimensions319LOGICAL :: Found(7) ! True if SIF definitions found320CHARACTER (len = MAX_NAME_LEN) :: FileName ! File name for reading the data (of .nc format)321CHARACTER (len = MAX_NAME_LEN) :: Var_Name, T_Name, Mask_Name322CHARACTER (len = MAX_NAME_LEN), ALLOCATABLE :: Dim_Names(:) ! Contains the opened NetCDF dimension variables323REAL(KIND=dp) :: Mask_Limit ! Value limit where masking starts to take effect324INTEGER :: loop, alloc_stat,dim_count,status ! Status tells whether operations succeed325INTEGER :: size_coord, size_const ! Temps for amounts of NetCDF coordinate and constant dimensions326LOGICAL :: tmpBool ,IsTimeDependent ! True, if time is used when accessing NetCDF327CHARACTER (len = MAX_NAME_LEN), ALLOCATABLE :: Coords(:), Constants(:) ! Contains the names for NetCDF coordinate and constant dimensions328INTEGER, ALLOCATABLE :: Permutation(:) ! Contains the NetCDF Access permutation for Coords and Constants329CHARACTER (len = 10) :: tmpFormat330331!------------------------------------------------------------------------------332! NetCDF INITIALIZATIONS333!------------------------------------------------------------------------------334335!-------------------------------------------------------------------------------336! 1) Gathers basic data from SIF337!-------------------------------------------------------------------------------338339!--- Collects the input information from Solver Input File340FileName = GetString( GetSolverParams(Solver), "File Name", Found(1) )341Var_Name = GetString( GetSolverParams(Solver), "Var Name", Found(2) )342343!--- Collects the NetCDF accessing information (coordinates, constant dimensions, time)344CALL GetNetCDFAccessParameters( GetSolverParams(Solver), Coords, Constants, Permutation, Found(3:4) )345T_Name = GetString( GetSolverParams(Solver), "Time Name", IsTimeDependent ) ! If given, time is the last dimension346347! Following parameters are needed for masking and coordinate system348Mask_Name = GetString( GetSolverParams(Solver), "Mask Variable", Found(5) )349Mask_Limit = GetConstReal( Solver % Values, "Mask Limit", Found(6) )350Coord_System = GetString( GetSolverParams(Solver), "Coordinate System", Found(7) ) ! Any input is ok; only valid gives a conversion and error is given otherwise351IF ( .NOT. Found(7) ) Coord_System = '' ! Initializes Coord_System, if not given352353!-------------------------------------------------------------------------------354! 2) Opening the NetCDF file and finding the variable355!-------------------------------------------------------------------------------356357DO loop = 1,2,1358IF ( .NOT. Found(loop) ) THEN ! Checks that the constants have been found successfully359CALL Fatal('GridDataMapper', &360"Unable to find a compulsory NetCDF Name Constant (the name of file or variable)")361END IF362END DO363364status = NF90_OPEN(FileName,NF90_NOWRITE,NCID) ! Read-only365IF ( G_Error(status, "NetCDF file could not be opened") ) THEN366CALL abort() ! End execution367END IF368369! Find variable to be accessed370status = NF90_INQ_VARID(NCID,Var_Name,Var_ID)371IF ( G_Error(status,'NetCDF variable name not found.') ) THEN372CALL abort()373END IF374375376!-------------------------------------------------------------------------------377! 3) Finds the amounts for used coordinate and constant dimensions378!-------------------------------------------------------------------------------379380!--- Defining coordinate, constant dimension and total dimension sizes381size_coord = 0382size_const = 0383IF ( Found(3) ) size_coord = size(Coords,1)384IF ( Found(4) ) size_const = size(Constants,1)385dim_count = size_coord + size_const386387IF ( (dim_count .EQ. 0) .AND. (.NOT. IsTimeDependent) ) THEN388CALL Fatal('GridDataMapper','Expected at least one indexing variable: time, coordinate, or constant.')389END IF390!> dim_count in range ( 0, (size_coord + size_const) ), and at least one possible NetCDF accessing parameter given391392!------------------------------------------------------------------------------393! 4) Obtains the used Elmer coordinate dimensionality (DIM)394!------------------------------------------------------------------------------395396DIM = size_coord397398!-------------------------------------------------------------------------------399! 5) Forms an array of dimension names (constant and coordinate) for accessing400!-------------------------------------------------------------------------------401WRITE (Message,'(A,I3,A)') 'Using ',dim_count,' input dimensions.'402CALL Info('GridDataMapper',Message)403404IF ( dim_count .GT. 0 ) THEN405406! Form an array of wanted names for defining the information407ALLOCATE (Dim_Names(dim_count), dim_ids(dim_count), dim_lens(dim_count), STAT = alloc_stat)408IF ( alloc_stat .NE. 0 ) THEN409CALL Fatal('GridDataMapper','Memory ran out')410END IF411412! Initialization in case of errors413Dim_Names = 'none'414dim_ids = -1415dim_lens = -1416417! Adds the coordinate NetCDF dimension names, if available418IF ( size_coord .GT. 0 ) Dim_Names(1:size(Coords)) = Coords(:)419420! Adds the constant NetCDF dimension names, if available421IF ( size_const .GT. 0 ) THEN422IF ( size_coord .GT. 0 ) THEN423Dim_Names((size(Coords)+1):size(Dim_Names)) = Constants(:)424ELSE425Dim_Names(:) = Constants(:)426END IF427END IF428429END IF430!> If there are dimensions, their names are in Dim_Names = [Coords, Constants]431432!-------------------------------------------------------------------------------433! 6) Gets dimensions on basis of the given names434!-------------------------------------------------------------------------------435IF ( dim_count .GT. 0 ) CALL GetAllDimensions(NCID,Dim_Names,dim_ids,dim_lens)436!> dim_ids & dim_lens collected with the Dim_Names437438!-------------------------------------------------------------------------------439! 7) Initializes the Grids (1/2)440!------------------------------------------------------------------------------441442!--- Default initializations for all cases443DO loop = 1,size(Grids,1),1444CALL InitGrid(Grids(loop), dim_count, size_coord )445Grids(loop) % access_perm = Permutation446END DO447448!-------------------------------------------------------------------------------449! Connects the Elmer Mesh dimensions to NetCDF access parameters450!-------------------------------------------------------------------------------451452453!--- Initializations for the case of having some real content454IF ( Grids(1) % IS_DEF ) THEN455456!--- Obtains the preliminary definining parameters for the NetCDF grid457CALL GetNetCDFGridParameters(NCID,Grids(1),dim_ids,dim_lens) ! Normal grid parameters don't depend on time458459!--- Connects every NetCDF access coordinate to a Elmer coordinate460DO loop = 1,Grids(1) % COORD_COUNT,1461462WRITE(tmpFormat,'(A,I1,A)') '(A,I',IntWidth(loop),',A)'463WRITE(Message,tmpFormat) 'Coordinate ', Grids(1) % ACCESS_PERM( loop ), ' To Elmer Dimension'464465Grids(1) % Elmer_perm( loop ) = &466GetInteger(GetSolverParams(Solver),Message,tmpBool)467IF ( .NOT. tmpBool ) THEN468WRITE(Message,'(A,I3,A)') 'Declared Coordinate Name ', Grids(1) % ACCESS_PERM( loop ),&469' is not connected to a Elmer dimension. Check all "Coordinate X To Elmer Dimension" definitions.'470CALL Fatal('GridDataMapper',Message)471END IF472END DO473474!--- Finds the index values for the found constant dimensions475DO loop = 1,size(Grids(1) % const_vals),1476477WRITE(tmpFormat,'(A,I1,A)') '(A,I',IntWidth(loop),')'478WRITE(Message,tmpFormat) 'NetCDF Constant Value ', Grids(1) % ACCESS_PERM( Grids(1) % COORD_COUNT + loop)479480Grids(1) % const_vals(loop) = GetInteger(GetSolverParams(Solver),Message,tmpBool)481IF ( .NOT. tmpBool ) THEN482WRITE(Message,'(A,I3,A)') 'Declared NetCDF Constant ', Grids(1) % ACCESS_PERM( Grids(1) % COORD_COUNT + loop),&483' has no corresponding index value. Check all NetCDF Constants.'484CALL Fatal('GridDataMapper',Message)485END IF486END DO487Grids(2) % const_vals = Grids(1) % const_vals488END IF489!> Grids initialized with constant values,x0,dx,nmax, and default for others; or Grid % IS_DEF is .FALSE.490491!-------------------------------------------------------------------------------492! 8) Initializes Time (if it is defined)493!-------------------------------------------------------------------------------494495IF (IsTimeDependent) THEN496497! Inform about the fate of time498CALL Info('GridDataMapper','Time dimension taken into account.')499500Time % is_defined = .TRUE.501CALL InitTime( Solver, NCID, T_Name, IS_TRANSIENT, STEP_SIZE, MAX_STEPS, Time )502503! If there'll be interpolation, initialize both of the grids usable504IF ( Grids(1) % IS_DEF ) THEN505IF ( Time % doInterpolation ) THEN506Grids(2) % x0(:) = Grids(1) % x0(:)507Grids(2) % dx(:) = Grids(1) % dx(:)508Grids(2) % nmax(:) = Grids(1) % nmax(:)509END IF510511IF ( size_coord .EQ. 2 ) THEN512IF ( Found(5) .AND. Found(6) ) THEN513CALL Info('GridDataMapper','Two dimensional NetCDF grid focusing on basis of the given mask is in effect.')514CALL Focus2DNetCDFGrid(NCID,Mask_Name,Mask_Limit,Grids(1),Time % low,dim_lens)515IF ( Time % doInterpolation ) THEN ! Need to interpolate, return two different grid parameters516517Grids(2) % x0(:) = Grids(1) % x0(:) ! Copy the same results obtained for all grids518Grids(2) % dx(:) = Grids(1) % dx(:)519Grids(2) % nmax(:) = Grids(1) % nmax(:)520CALL Focus2DNetCDFGrid(NCID,Mask_Name,Mask_Limit,Grids(2),Time % high,dim_lens)521END IF522ELSE523! No mask used524END IF525END IF526END IF527END IF528!> Time initialized and Grids adjusted, if time-dependent focusing used529530!-------------------------------------------------------------------------------531! 9) Initializes the Grids (2/2) ( depends on Focus2DNetCDFGrid() )532!-------------------------------------------------------------------------------533IF ( Grids(1) % IS_DEF ) THEN534DO loop = 1,size(Grids,1),1535Grids(loop) % x1(:) = Grids(loop) % x0(:) +&536(Grids(loop) % nmax(:)-1) * Grids(loop) % dx(:) ! In 3D case opposite points of the cube; if only one dimension, will be 0537END DO538539END IF540!> Grids initialized with proper x1's541542!-------------------------------------------------------------------------------543!> Phase 1: Coord_System544!> Phase 2: NCID, Var_ID545!> Phase 4: DIM546!> Phase 6: dim_ids, dim_lens547!> Phase 8: Time548!> Phase 9: Grids (scale(:), move(:) and eps(:) not touched)549IF ( DEBUG ) THEN550CALL PrintGrid(Grids(1),1)551CALL PrintGrid(Grids(2),2)552END IF553554END SUBROUTINE InitNetCDF555556557!---------------- InitTime() ------------------------558!--- Initializes the time values559SUBROUTINE InitTime( Solver, NCID, T_Name, IS_TRANSIENT, STEP_SIZE, MAX_STEPS, TimeResult )560!----------------------------------------------------561USE NetCDFGeneralUtils, ONLY: TimeValueToIndex, GetDimension562USE DefUtils, ONLY: MAX_NAME_LEN, GetSolverParams, GetLogical, GetCReal, GetTime, GetConstReal563USE Messages, ONLY: Message, Info, Fatal564IMPLICIT NONE565!-------------------------------------------------------------------------------566! ARGUMENTS567!-------------------------------------------------------------------------------568!--- A) Input569TYPE(Solver_t), INTENT(IN) :: Solver570INTEGER, INTENT(IN) :: NCID571LOGICAL, INTENT(IN) :: IS_TRANSIENT572CHARACTER(len=MAX_NAME_LEN), INTENT(IN) :: T_Name573REAL(KIND=dp), INTENT(IN) :: STEP_SIZE574INTEGER, INTENT(IN) :: MAX_STEPS575!--- B) Output576TYPE(TimeType_t), INTENT(OUT) :: TimeResult577578!-------------------------------------------------------------------------------579! VARIABLES580!-------------------------------------------------------------------------------581LOGICAL :: IsTimeIndex, IsUserDefined, Found(5) ! True if SIF definitions found582REAL(KIND=dp) :: TimeBias, Time, TimeEpsilon ! Biasing for every used Elmer time value/index583584!-------------------------------------------------------------------------------585! 1) Gathers data from SIF, applies default values586!-------------------------------------------------------------------------------587IsUserDefined = GetLogical( GetSolverParams(Solver), "User Defines Time", Found(1) ) ! Set to true, if old definitions are used588IsTimeIndex = GetLogical( GetSolverParams(Solver), "Is Time Index", Found(2) ) ! If true, then the given time value is an index (Default: value)589TimeBias = GetCReal( GetSolverParams(Solver), "NetCDF Starting Time", Found(3) ) ! Index, if IsTimeIndex is true; value otherwise590TimeEpsilon = GetConstReal( GetSolverParams(Solver), "Epsilon Time", Found(5) ) ! The tolerance for the time value591592!-------------------------------------------------------------------------------593! 2) Collects dimension specific data594!-------------------------------------------------------------------------------595CALL GetDimension(NCID,T_Name, TimeResult % id, TimeResult % len)596!> id and len set for TimeResult597598!-------------------------------------------------------------------------------599! 3) Sets default values, informs on effect600!-------------------------------------------------------------------------------601IF ( .NOT. Found(1) ) IsUserDefined = .FALSE.602IF ( .NOT. Found(2) ) IsTimeIndex = .FALSE. ! Defaulted to False for values are more natural, otherwise set as given603IF ( .NOT. Found(3) ) THEN604IF ( IsTimeIndex ) THEN605TimeBias = 1.0_dp ! Starts, by default, from index 1606ELSE607TimeBias = 0.0_dp ! Starts, by default, without value adjustment608END IF609ELSE610! Tell the user what is happening611IF ( IsTimeIndex ) THEN612WRITE (Message,'(A,F6.2)') 'Input time indices are adjusted (summed) by ', TimeBias613ELSE614WRITE (Message,'(A,F6.2)') 'Input time values are adjusted (summed) by ', TimeBias615END IF616CALL Info('GridDataMapper',Message)617END IF618IF ( .NOT. Found(5) ) THEN619TimeEpsilon = 0.0_dp620ELSE621WRITE (Message,'(A,F6.3)') 'Received Time Epsilon with value ', TimeEpsilon622CALL Info('GridDataMapper',Message)623END IF624!> Default values set625626!-------------------------------------------------------------------------------627! 4) Handles transient cases (uses Elmer time, if not defined otherwise)628!-------------------------------------------------------------------------------629IF ( IS_TRANSIENT .AND. (.NOT. IsUserDefined ) ) THEN630631!-----------------------------------------------------------------------------632! A) Transient with Elmer time points633!-----------------------------------------------------------------------------634WRITE(Message, '(A,A)') 'Simulation is transient and user time input is ignored.',&635' (If own time scaling wanted, set SIF variable "User Defines Time" true and use user defined functions)'636CALL Info('GridDataMapper', Message)637638!--- Get the time from Elmer639Time = GetTime()640641IF ( IsTimeIndex ) THEN642!---------------------------------------------------------------------------643! Bias time indices644!---------------------------------------------------------------------------645! Indexing starts with step size in Elmer, bias it to first index646647!--- Check the bias doesn't cause over-indexing the NetCDF time range648IF ( TimeBias .LT. 1.0_dp .OR. TimeBias .GT. TimeResult % LEN ) THEN649WRITE (Message, '(A,F6.2,A,I5,A)') 'NetCDF Starting Time index ', TimeBias, &650' does not fit within the NetCDF time index range (1,', TimeResult % LEN,')'651CALL Fatal('GridDataMapper', Message)652END IF653654!--- Checks the bias doesn't indirectly over-index due to iterations655IF (MAX_STEPS .GT. ((TimeResult % LEN - (TimeBias - STEP_SIZE))/STEP_SIZE) ) THEN656WRITE (Message, '(A,I5,A,F10.2,A,F6.2,A)') 'Defined amount of timestep intervals ', MAX_STEPS, &657' is more than ', ((TimeResult % LEN - (TimeBias - STEP_SIZE))/STEP_SIZE),&658', which is the maximum number of allowed size ', STEP_SIZE ,' steps on the NetCDF grid.'659CALL Fatal('GridDataMapper',Message)660END IF661662!--- Perform biasing (the bias is valid)663Time = Time + (TimeBias - STEP_SIZE)664ELSE665!---------------------------------------------------------------------------666! Bias time values667!---------------------------------------------------------------------------668Time = Time + TimeBias669! NOTE: Time value is checked when it's converted to a time index with TimeValueToIndex()670! Does not check for eventual over-indexing!671END IF672673ELSE674675!-----------------------------------------------------------------------------676! B) For user defined and steady state677!-----------------------------------------------------------------------------678! NOTE: User-defined/steady state never biased!679Time = GetCReal( Solver % Values, "Time Point", Found(4) )680681IF ( .NOT. Found(4) ) THEN682WRITE(Message,'(A,I3,A)') 'No time point given; specify it in the Solver Input File with name "Time Point"&683or enable transient simulation!'684CALL Fatal('GridDataMapper',Message)685END IF686687END IF688!> Time automatic and transient => Time biased689!> Time user-defined/steady state => Time obtained directly from SIF690691!--- Converts the given time value into an appropriate time index692IF (.NOT. IsTimeIndex) Time = TimeValueToIndex(NCID,T_Name,TimeResult % id,TimeResult % LEN,Time, TimeEpsilon)693694!--- Final check before letting through695IF ( Time .LT. 1 .OR. Time .GT. TimeResult % LEN ) THEN696WRITE (Message, '(A,F6.2,A,I5,A)') 'Time value ', Time, ' is out of range (1,', TimeResult % LEN, ')'697CALL Fatal('GridDataMapper',Message)698END IF699!> Time values are converted to indices and checked that they are within range; eventual over-indexing not always checked700!> I.e. Time is obtained and checked to be within range701702!-------------------------------------------------------------------------------703! 5) Finalizes TimeResult704!-------------------------------------------------------------------------------705706! Rounds to nearest integer index, if it is within epsilon range, to accomodate for insignificant differences between real values707IF ( Found(5) .AND. (FLOOR( Time) .NE. CEILING( Time )) ) THEN708WRITE (Message,'(A,F8.5,A,F8.5)') 'The time index with epsilon range: ', Time - FLOOR(Time), ' (+/-) ', TimeEpsilon709CALL Info('GridDataMapper',Message)710! FLOOR(Time) < Time < CEILING(TIME) <=> 0 < Time - FLOOR(Time) < CEILING(TIME) - FLOOR(TIME) = 1711! If Epsilon makes the value exceed either limit, then the limit is where it is rounded; otherwise intact712IF ( Time - FLOOR( Time ) .LE. TimeEpsilon ) THEN713Time = FLOOR( Time )714ELSE IF ( Time - FLOOR( Time ) .GE. 1.0_dp - TimeEpsilon ) THEN715Time = CEILING( Time )716END IF717END IF718TimeResult % val = Time719TimeResult % low = FLOOR( Time )720TimeResult % high = CEILING( Time )721TimeResult % doInterpolation = (TimeResult % low .NE. TimeResult % high)722IF ( TimeResult % len .EQ. 1 ) TimeResult % doInterpolation = .FALSE. ! No need to interpolate unit time723IF ( TimeResult % low .LT. 1 ) TimeResult % low = 1724IF ( TimeResult % high .GT. TimeResult % len ) TimeResult % high = TimeResult % len725726IF ( TimeResult % doInterpolation ) THEN727WRITE (Message,'(A,F5.2,A)') 'Given time value ', TimeResult % val , ' is not an integer. Using time interpolation.'728CALL Info('GridDataMapper',Message)729ELSE730WRITE (Message,'(A,F5.1,A)') 'Given time value ', TimeResult % val, ' is an integer. No time interpolation used.'731CALL Info('GridDataMapper',Message)732END IF733734!-------------------------------------------------------------------------------735736END SUBROUTINE InitTime737738739!---------------- InitInterpolation() ---------------740!--- Initializes the information needed for interpolation741SUBROUTINE InitInterpolation( Solver, DIM, Grids, TimeInterpolationMethod, InterpMultiplier, InterpBias )742USE DefUtils, ONLY: GetSolverParams, MAX_NAME_LEN, GetConstReal, GetString, GetCReal, CoordinateSystemDimension743USE Messages744IMPLICIT NONE745746!-------------------------------------------------------------------------------747! ARGUMENTS748!-------------------------------------------------------------------------------749TYPE(Solver_t), INTENT(IN) :: Solver750INTEGER, INTENT(IN) :: DIM751TYPE(UniformGrid_t), INTENT(INOUT) :: Grids(:)752REAL(KIND=dp), INTENT(OUT) :: InterpMultiplier, InterpBias753CHARACTER(len=MAX_NAME_LEN), INTENT(OUT) :: TimeInterpolationMethod754755!-------------------------------------------------------------------------------756! VARIABLES757!-------------------------------------------------------------------------------758LOGICAL :: tmpBool759REAL(KIND=dp), ALLOCATABLE :: eps(:)760INTEGER :: loop, alloc_stat761762!-------------------------------------------------------------------------------763! 1) Adds Epsilon values to Grids (if applicable)764!-------------------------------------------------------------------------------765IF ( Grids(1) % COORD_COUNT .GT. 0 ) THEN766767!--- Allocation768ALLOCATE ( eps( Grids(1) % COORD_COUNT ), STAT = alloc_stat )769IF ( alloc_stat .NE. 0 ) THEN770CALL Fatal('GridDataMapper','Memory ran out')771END IF772eps = 0773774! Epsilons are the relative tolerances for the amount775! the Elmer grid point misses the bounds of the NetCDF bounding box776DO loop = 1,size(eps),1777778! NOTE: There won't be more than 9 epsilons, because there can't be enough Elmer coordinates for that!779WRITE(Message, '(A,I1)') 'Epsilon ', loop780eps(loop) = GetConstReal(GetSolverParams(Solver), Message, tmpBool)781IF ( .NOT. tmpBool ) THEN782eps(loop) = 0783WRITE(Message,'(A,I1,A,A)') 'Variable "Epsilon ', loop ,'" not given in Solver Input File. ',&784'Using zero tolerance for NetCDF grid mismatches with Elmer mesh.'785CALL Warn('GridDataMapper', Message)786END IF787END DO788789! Sets the appropriate values to the Grids790Grids(1) % Eps(:) = eps(:) * Grids(1) % dx(:)791Grids(2) % Eps(:) = eps(:) * Grids(2) % dx(:)792END IF793794!-------------------------------------------------------------------------------795! 2) Sets the time interpolation method796!-------------------------------------------------------------------------------797TimeInterpolationMethod = GetString( GetSolverParams(Solver), "Time Interpolation Method", tmpBool )798IF ( .NOT. tmpBool ) THEN799CALL Warn('GridDataMapper', 'SIF variable "Time Interpolation Method" not specified, using default settings.')800TimeInterpolationMethod = ''801ELSE802WRITE (Message,'(A,A)' ) 'Received Time Interpolation Method SIF variable value: ', TimeInterpolationMethod803CALL Info('GridDataMapper', Message)804END IF805806!-------------------------------------------------------------------------------807! 3) Sets the final adjustments for the interpolation results (to allow relative/absolute time, f.ex.)808!-------------------------------------------------------------------------------809810! If absolute time is relative, the value of the time function is added to the interpolated location; otherwise it is multiplied with it811InterpMultiplier = GetCReal( GetSolverParams(Solver), "Interpolation Multiplier", tmpBool ) ! Multiplies the final interpolation result by given number (relative time)812IF ( .NOT. tmpBool ) InterpMultiplier = 1.0_dp ! Defaulted to 1, so it doesn't modify the result813814InterpBias = GetCReal( GetSolverParams(Solver), "Interpolation Bias", tmpBool ) ! Adds the bias to the final interpolation result (absolute time)815IF ( .NOT. tmpBool ) InterpBias = 0.0_dp ! Defaulted to 0, so there is no bias on time816817!-------------------------------------------------------------------------------818819END SUBROUTINE InitInterpolation820821!------------------------------------------------------------------------------822END SUBROUTINE GridDataMapper823!------------------------------------------------------------------------------824825826827