@@ -58,7 +58,7 @@ def __init__(self, filename=None, **kwargs):
58
58
if filename :
59
59
self .read (filename , ** kwargs )
60
60
61
- def read (self , filename = None , header_only = False ):
61
+ def read (self , filename = None , header_only = False , tdecimals = 8 ):
62
62
""" read BTS file, with field:
63
63
u (3 x nt x ny x nz)
64
64
uTwr (3 x nt x nTwr)
@@ -98,11 +98,11 @@ def read(self, filename=None, header_only=False):
98
98
self ['uTwr' ] = uTwr
99
99
self ['info' ] = info
100
100
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
102
102
self ['y' ] = np .arange (ny )* dy
103
103
self ['y' ] -= np .mean (self ['y' ]) # y always centered on 0
104
104
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 )
106
106
self ['zTwr' ] = - np .arange (nTwr )* dz + zBottom
107
107
self ['zRef' ] = zHub
108
108
self ['uRef' ] = uHub
@@ -592,45 +592,13 @@ def __repr__(self):
592
592
s += ' ux: min: {}, max: {}, mean: {} \n ' .format (np .min (ux ), np .max (ux ), np .mean (ux ))
593
593
s += ' uy: min: {}, max: {}, mean: {} \n ' .format (np .min (uy ), np .max (uy ), np .mean (uy ))
594
594
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 '
596
600
return s
597
601
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
-
634
602
def toDataFrame (self ):
635
603
dfs = {}
636
604
@@ -713,31 +681,167 @@ def toDataFrame(self):
713
681
# pass
714
682
return dfs
715
683
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
716
752
717
753
# 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' ):
719
818
"""
720
819
Convert current TurbSim file into one generated from AMR-Wind LES sampling data in .nc format
721
820
Assumes:
722
821
-- u, v, w (nt, nx * ny * nz)
723
822
-- u is aligned with x-axis (flow is not rotated) - this consideration needs to be added
724
823
824
+
725
825
INPUTS:
726
826
- 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")
728
828
- dt: timestep size [s]
729
829
- nt: number of timesteps (sequential) you want to read in, starting at the first timestep available
830
+ INPUTS: TODO
730
831
- y: user-defined vector of coordinate positions in y
731
832
- z: user-defined vector of coordinate positions in z
732
833
- uref: (float) reference mean velocity (e.g. 8.0 hub height mean velocity from input file)
733
834
- zref: (float) hub height (e.t. 150.0)
734
835
"""
735
836
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)' )
736
840
737
841
# read in sampling data plane
738
842
ds = xr .open_dataset (filename ,
739
843
engine = 'netcdf4' ,
740
- group = plane_label )
844
+ group = sampling_identifier )
741
845
ny , nz , _ = ds .attrs ['ijk_dims' ]
742
846
noffsets = len (ds .attrs ['offsets' ])
743
847
t = np .arange (0 , dt * (nt - 0.5 ), dt )
0 commit comments