@@ -58,7 +58,7 @@ def __init__(self, filename=None, **kwargs):
5858 if filename :
5959 self .read (filename , ** kwargs )
6060
61- def read (self , filename = None , header_only = False ):
61+ def read (self , filename = None , header_only = False , tdecimals = 8 ):
6262 """ read BTS file, with field:
6363 u (3 x nt x ny x nz)
6464 uTwr (3 x nt x nTwr)
@@ -98,11 +98,11 @@ def read(self, filename=None, header_only=False):
9898 self ['uTwr' ] = uTwr
9999 self ['info' ] = info
100100 self ['ID' ] = ID
101- self ['dt' ] = np .round (dt ,3 ) # dt is stored in single precision in the TurbSim output
101+ self ['dt' ] = np .round (dt , tdecimals ) # dt is stored in single precision in the TurbSim output
102102 self ['y' ] = np .arange (ny )* dy
103103 self ['y' ] -= np .mean (self ['y' ]) # y always centered on 0
104104 self ['z' ] = np .arange (nz )* dz + zBottom
105- self ['t' ] = np .round (np .arange (nt )* dt , 3 )
105+ self ['t' ] = np .round (np .arange (nt )* dt , tdecimals )
106106 self ['zTwr' ] = - np .arange (nTwr )* dz + zBottom
107107 self ['zRef' ] = zHub
108108 self ['uRef' ] = uHub
@@ -592,45 +592,13 @@ def __repr__(self):
592592 s += ' ux: min: {}, max: {}, mean: {} \n ' .format (np .min (ux ), np .max (ux ), np .mean (ux ))
593593 s += ' uy: min: {}, max: {}, mean: {} \n ' .format (np .min (uy ), np .max (uy ), np .mean (uy ))
594594 s += ' uz: min: {}, max: {}, mean: {} \n ' .format (np .min (uz ), np .max (uz ), np .mean (uz ))
595-
595+ s += ' Useful methods:\n '
596+ s += ' - read, write, toDataFrame, keys\n '
597+ s += ' - valuesAt, vertProfile, horizontalPlane, verticalPlane, closestPoint\n '
598+ s += ' - fitPowerLaw\n '
599+ s += ' - makePeriodic, checkPeriodic\n '
596600 return s
597601
598- def toDataSet (self , datetime = False ):
599- import xarray as xr
600-
601- if datetime :
602- timearray = pd .to_datetime (self ['t' ], unit = 's' , origin = pd .to_datetime ('2000-01-01 00:00:00' ))
603- timestr = 'datetime'
604- else :
605- timearray = self ['t' ]
606- timestr = 'time'
607-
608- ds = xr .Dataset (
609- data_vars = dict (
610- u = ([timestr ,'y' ,'z' ], self ['u' ][0 ,:,:,:]),
611- v = ([timestr ,'y' ,'z' ], self ['u' ][1 ,:,:,:]),
612- w = ([timestr ,'y' ,'z' ], self ['u' ][2 ,:,:,:]),
613- ),
614- coords = {
615- timestr : timearray ,
616- 'y' : self ['y' ],
617- 'z' : self ['z' ],
618- },
619- )
620-
621- # Add mean computations
622- ds ['up' ] = ds ['u' ] - ds ['u' ].mean (dim = timestr )
623- ds ['vp' ] = ds ['v' ] - ds ['v' ].mean (dim = timestr )
624- ds ['wp' ] = ds ['w' ] - ds ['w' ].mean (dim = timestr )
625-
626- if datetime :
627- # Add time (in s) to the variable list
628- ds ['time' ] = (('datetime' ), self ['t' ])
629-
630- return ds
631-
632-
633-
634602 def toDataFrame (self ):
635603 dfs = {}
636604
@@ -713,31 +681,167 @@ def toDataFrame(self):
713681 # pass
714682 return dfs
715683
684+ def toDataset (self ):
685+ """
686+ Convert the data that was read in into a xarray Dataset
687+
688+ # TODO SORT OUT THE DIFFERENCE WITH toDataSet
689+ """
690+ from xarray import IndexVariable , DataArray , Dataset
691+
692+ print ('[TODO] pyFAST.input_output.turbsim_file.toDataset: merge with function toDataSet' )
693+
694+ y = IndexVariable ("y" , self .y , attrs = {"description" :"lateral coordinate" ,"units" :"m" })
695+ zround = np .asarray ([np .round (zz ,6 ) for zz in self .z ]) #the open function here returns something like *.0000000001 which is annoying
696+ z = IndexVariable ("z" , zround , attrs = {"description" :"vertical coordinate" ,"units" :"m" })
697+ time = IndexVariable ("time" , self .t , attrs = {"description" :"time since start of simulation" ,"units" :"s" })
698+
699+ da = {}
700+ for component ,direction ,velname in zip ([0 ,1 ,2 ],["x" ,"y" ,"z" ],["u" ,"v" ,"w" ]):
701+ # the dataset produced here has y/z axes swapped relative to data stored in original object
702+ velocity = np .swapaxes (self ["u" ][component ,...],1 ,2 )
703+ da [velname ] = DataArray (velocity ,
704+ coords = {"time" :time ,"y" :y ,"z" :z },
705+ dims = ["time" ,"y" ,"z" ],
706+ name = "velocity" ,
707+ attrs = {"description" :"velocity along {0}" .format (direction ),"units" :"m/s" })
708+
709+ return Dataset (data_vars = da , coords = {"time" :time ,"y" :y ,"z" :z })
710+
711+ def toDataSet (self , datetime = False ):
712+ """
713+ Convert the data that was read in into a xarray Dataset
714+
715+ # TODO SORT OUT THE DIFFERENCE WITH toDataset
716+ """
717+ import xarray as xr
718+
719+ print ('[TODO] pyFAST.input_output.turbsim_file.toDataSet: should be discontinued' )
720+ print ('[TODO] pyFAST.input_output.turbsim_file.toDataSet: merge with function toDataset' )
721+
722+ if datetime :
723+ timearray = pd .to_datetime (self ['t' ], unit = 's' , origin = pd .to_datetime ('2000-01-01 00:00:00' ))
724+ timestr = 'datetime'
725+ else :
726+ timearray = self ['t' ]
727+ timestr = 'time'
728+
729+ ds = xr .Dataset (
730+ data_vars = dict (
731+ u = ([timestr ,'y' ,'z' ], self ['u' ][0 ,:,:,:]),
732+ v = ([timestr ,'y' ,'z' ], self ['u' ][1 ,:,:,:]),
733+ w = ([timestr ,'y' ,'z' ], self ['u' ][2 ,:,:,:]),
734+ ),
735+ coords = {
736+ timestr : timearray ,
737+ 'y' : self ['y' ],
738+ 'z' : self ['z' ],
739+ },
740+ )
741+
742+ # Add mean computations
743+ ds ['up' ] = ds ['u' ] - ds ['u' ].mean (dim = timestr )
744+ ds ['vp' ] = ds ['v' ] - ds ['v' ].mean (dim = timestr )
745+ ds ['wp' ] = ds ['w' ] - ds ['w' ].mean (dim = timestr )
746+
747+ if datetime :
748+ # Add time (in s) to the variable list
749+ ds ['time' ] = (('datetime' ), self ['t' ])
750+
751+ return ds
716752
717753 # Useful converters
718- def fromAMRWind (self , filename , dt , nt ):
754+ def fromAMRWind (self , filename , timestep , output_frequency , sampling_identifier , verbose = 1 , fileout = None , zref = None , xloc = None ):
755+ """
756+ Reads a AMRWind netcdf file, grabs a group of sampling planes (e.g. p_slice),
757+ return an instance of TurbSimFile, optionally write turbsim file to disk
758+
759+
760+ Parameters
761+ ----------
762+ filename : str,
763+ full path to netcdf file generated by amrwind
764+ timestep : float,
765+ amr-wind code timestep (time.fixed_dt)
766+ output_frequency : int,
767+ frequency chosen for sampling output in amrwind input file (sampling.output_frequency)
768+ sampling_identifier : str,
769+ identifier of the sampling being requested (an entry of sampling.labels in amrwind input file)
770+ zref : float,
771+ height to be written to turbsim as the reference height. if none is given, it is taken as the vertical centerpoint of the slice
772+ """
773+ try :
774+ from pyFAST .input_output .amrwind_file import AMRWindFile
775+ except :
776+ try :
777+ from .amrwind_file import AMRWindFile
778+ except :
779+ from amrwind_file import AMRWindFile
780+
781+ obj = AMRWindFile (filename ,timestep ,output_frequency , group_name = sampling_identifier )
782+
783+ self ["u" ] = np .ndarray ((3 ,obj .nt ,obj .ny ,obj .nz ))
784+
785+ xloc = float (obj .data .x [0 ]) if xloc is None else xloc
786+ if verbose :
787+ print ("Grabbing the slice at x={0} m" .format (xloc ))
788+ self ['u' ][0 ,:,:,:] = np .swapaxes (obj .data .u .sel (x = xloc ).values ,1 ,2 )
789+ self ['u' ][1 ,:,:,:] = np .swapaxes (obj .data .v .sel (x = xloc ).values ,1 ,2 )
790+ self ['u' ][2 ,:,:,:] = np .swapaxes (obj .data .w .sel (x = xloc ).values ,1 ,2 )
791+ self ['t' ] = obj .data .t .values
792+
793+ self ['y' ] = obj .data .y .values
794+ self ['z' ] = obj .data .z .values
795+ self ['dt' ] = obj .output_dt
796+
797+ self ['ID' ] = 7
798+ ltime = time .strftime ('%d-%b-%Y at %H:%M:%S' , time .localtime ())
799+ self ['info' ] = 'Converted from AMRWind output file {0} {1:s}.' .format (filename ,ltime )
800+
801+ iz = int (obj .nz / 2 )
802+ self ['zRef' ] = float (obj .data .z [iz ]) if zref is None else zref
803+ if verbose :
804+ print ("Setting the TurbSim file reference height to z={0} m" .format (self ["zRef" ]))
805+
806+ self ['uRef' ] = float (obj .data .u .sel (x = xloc ).sel (y = 0 ).sel (z = self ["zRef" ]).mean ().values )
807+ self ['zRef' ], self ['uRef' ], bHub = self .hubValues ()
808+
809+ if fileout is not None :
810+ filebase = os .path .splitext (filename )[1 ]
811+ fileout = filebase + ".bts"
812+ if verbose :
813+ print ("===> {0}" .format (fileout ))
814+ self .write (fileout )
815+
816+
817+ def fromAMRWind_legacy (self , filename , dt , nt , y , z , sampling_identifier = 'p_sw2' ):
719818 """
720819 Convert current TurbSim file into one generated from AMR-Wind LES sampling data in .nc format
721820 Assumes:
722821 -- u, v, w (nt, nx * ny * nz)
723822 -- u is aligned with x-axis (flow is not rotated) - this consideration needs to be added
724823
824+
725825 INPUTS:
726826 - filename: (string) full path to .nc sampling data file
727- - plane_label : (string) name of sampling plane group from .inp file (e.g. "p_sw2")
827+ - sampling_identifier : (string) name of sampling plane group from .inp file (e.g. "p_sw2")
728828 - dt: timestep size [s]
729829 - nt: number of timesteps (sequential) you want to read in, starting at the first timestep available
830+ INPUTS: TODO
730831 - y: user-defined vector of coordinate positions in y
731832 - z: user-defined vector of coordinate positions in z
732833 - uref: (float) reference mean velocity (e.g. 8.0 hub height mean velocity from input file)
733834 - zref: (float) hub height (e.t. 150.0)
734835 """
735836 import xarray as xr
837+
838+ print ('[TODO] fromAMRWind_legacy: function might be unfinished. Merge with fromAMRWind' )
839+ print ('[TODO] fromAMRWind_legacy: figure out y, and z from data (see fromAMRWind)' )
736840
737841 # read in sampling data plane
738842 ds = xr .open_dataset (filename ,
739843 engine = 'netcdf4' ,
740- group = plane_label )
844+ group = sampling_identifier )
741845 ny , nz , _ = ds .attrs ['ijk_dims' ]
742846 noffsets = len (ds .attrs ['offsets' ])
743847 t = np .arange (0 , dt * (nt - 0.5 ), dt )
0 commit comments