From af29eadd522ba4ac6a57f30b11299c40c8b31f69 Mon Sep 17 00:00:00 2001 From: David Robert Verelst <dave@dtu.dk> Date: Mon, 3 Jul 2017 11:22:37 +0200 Subject: [PATCH] prepost.windIO: use what you asked for aero radius, log analysis fixes --- wetb/prepost/tests/test_windIO.py | 35 ++++++++--- wetb/prepost/windIO.py | 96 ++++++++++++++++++++----------- 2 files changed, 88 insertions(+), 43 deletions(-) diff --git a/wetb/prepost/tests/test_windIO.py b/wetb/prepost/tests/test_windIO.py index d495ad0f..afb9c738 100644 --- a/wetb/prepost/tests/test_windIO.py +++ b/wetb/prepost/tests/test_windIO.py @@ -41,7 +41,8 @@ class TestsLogFile(unittest.TestCase): self.assertEqual(len(log.MsgListLog2), 1) self.assertEqual(log.MsgListLog[0][0], fpath) self.assertTrue(fpath in log.MsgListLog2) - # the current log file doesn't contain any errors and didn't complete + # the current log file doesn't contain any errors but didn't complete + # [found_error, exit_correct] self.assertEqual(log.MsgListLog2[fpath], [False, False]) def test_loganalysis_file(self): @@ -62,13 +63,13 @@ class TestsLogFile(unittest.TestCase): self.assertAlmostEqual(df.loc[0,'mean_iters_p_time_step'], 1.96) self.assertTrue(np.isnan(df.loc[0,'seconds_p_iteration'])) - def test_read_and_analysis(self): + def test_read_and_analysis_simulation_error2(self): fname = 'simulation_error2.log' fpath = os.path.join(self.logpath, fname) log = self.readlog(fname) - # finish correctly, but with errors + # finish correctly, but with errors, [found_error, exit_correct] self.assertEqual(log.MsgListLog2[fpath], [True, True]) csv = log._header() @@ -88,20 +89,20 @@ class TestsLogFile(unittest.TestCase): self.assertAlmostEqual(df.loc[0,'real_sim_time'], 75.9183, places=4) self.assertTrue(np.isnan(df.loc[0,'seconds_p_iteration'])) - self.assertEqual(df.loc[0,'first_tstep_104'], 1385) - self.assertEqual(df.loc[0,'last_step_104'], 1387) + self.assertEqual(df.loc[0,'first_tstep_104'], 1386) + self.assertEqual(df.loc[0,'last_step_104'], 1388) self.assertEqual(df.loc[0,'nr_104'], 30) msg = ' *** ERROR *** Out of limits in user defined shear field - ' msg += 'limit value used' self.assertEqual(df.loc[0,'msg_104'], msg) - def test_read_and_analysis2(self): + def test_read_and_analysis_init_error(self): fname = 'init_error.log' fpath = os.path.join(self.logpath, fname) log = self.readlog(fname) - # finish correctly, but with errors + # errors, but no sim time or finish message [found_error, exit_correct] self.assertEqual(log.MsgListLog2[fpath], [True, True]) csv = log._header() @@ -114,7 +115,23 @@ class TestsLogFile(unittest.TestCase): msg = ' *** ERROR *** No line termination in command line 8' self.assertEqual(df.loc[0,'msg_5'], msg) - def test_read_and_analysis3(self): + def test_read_and_analysis_init(self): + + fname = 'init.log' + fpath = os.path.join(self.logpath, fname) + + log = self.readlog(fname) + # errors, but no sim time or finish message [found_error, exit_correct] + self.assertEqual(log.MsgListLog2[fpath], [False, False]) + + csv = log._header() + csv = log._msglistlog2csv(csv) + # because our API is really crappy, we emulate writing to StringIO + # instead of to a file + fcsv = io.StringIO(csv) + df = log.csv2df(fcsv) + + def test_read_and_analysis_tmp(self): fname = 'tmp.log' fpath = os.path.join(self.logpath, fname) @@ -190,7 +207,7 @@ class TestsLoadResults(unittest.TestCase): exp = [[38, 'global-blade2-elem-019-zrel-1.00-State pos-z', 'm'], [200, 'blade2-blade2-node-017-momentvec-z', 'kNm'], [296, 'blade1-blade1-node-008-forcevec-z', 'kN'], - [415, 'Cl-1-54.82', 'deg'], + [415, 'Cl-1-55.7', 'deg'], [421, 'qwerty-is-azerty', 'is'] ] for k in exp: diff --git a/wetb/prepost/windIO.py b/wetb/prepost/windIO.py index 9f4e8f95..1bf85790 100755 --- a/wetb/prepost/windIO.py +++ b/wetb/prepost/windIO.py @@ -176,11 +176,11 @@ class LogFile(object): else: iterations = np.ndarray( (len(lines),3), dtype=np.float32 ) dt = False - iterations[:,0:2] = -1 + iterations[:,0:2] = np.nan iterations[:,2] = 0 # keep track of the time_step number - time_step, init_block = -1, True + time_step, init_block = 0, True # check for messages in the current line # for speed: delete from message watch list if message is found for j, line in enumerate(lines): @@ -192,13 +192,13 @@ class LogFile(object): # keep track of the number of iterations if line[:12] == ' Global time': - time_step += 1 iterations[time_step,0] = float(line[14:40]) # for PY2, new line is 2 characters, for PY3 it is one char iterations[time_step,1] = int(line[-6:]) # time step is the first time stamp if not dt: dt = float(line[15:40]) + time_step += 1 # no need to look for messages if global time is mentioned continue @@ -235,10 +235,6 @@ class LogFile(object): elif msg in self.err_sim: icol = subcols_sim*self.err_sim[msg] icol += subcols_init*self.init_cols + 1 - # in case stuff already goes wrong on the first time step - if time_step == -1: - time_step = 0 - # 1: time step of first occurance if tempLog[icol] == '': tempLog[icol] = '%i' % time_step @@ -253,7 +249,7 @@ class LogFile(object): tempLog[icol+3] = line found_error = True - iterations[time_step,2] = 1 + iterations[time_step-1,2] = 1 # method of last resort, we have no idea what message elif line[:10] == ' *** ERROR' or line[:10]==' ** WARNING': @@ -264,13 +260,10 @@ class LogFile(object): # and message tempLog[icol+1] = line found_error = True - # in case stuff already goes wrong on the first time step - if time_step == -1: - time_step = 0 - iterations[time_step,2] = 1 + iterations[time_step-1,2] = 1 # remove not-used rows from iterations - iterations = iterations[:time_step+1,:] + iterations = iterations[:time_step,:] # simulation and simulation output time based on the tags # FIXME: ugly, do not mix tags with what is actually happening in the @@ -279,11 +272,15 @@ class LogFile(object): t_stop = float(case['[time_stop]']) duration = float(case['[duration]']) else: - t_stop = -1 + t_stop = np.nan duration = -1 + # if no time steps have passed + if iterations.shape == (0,3): + elapsed_time = -1 + tempLog.append('') # see if the last line holds the sim time - if line[:15] == ' Elapsed time :': + elif line[:15] == ' Elapsed time :': exit_correct = True elapsed_time = float(line[15:-1]) tempLog.append( elapsed_time ) @@ -291,24 +288,29 @@ class LogFile(object): # might be: " Closing of external type2 DLL" elif line[:20] == ' Closing of external': exit_correct = True - elapsed_time = iterations[time_step,0] + elapsed_time = iterations[time_step-1,0] tempLog.append( elapsed_time ) # FIXME: this is weird mixing of referring to t_stop from the tags # and the actual last recorded time step - elif np.allclose(iterations[time_step,0], t_stop): + elif np.allclose(iterations[time_step-1,0], t_stop): exit_correct = True - elapsed_time = iterations[time_step,0] + elapsed_time = iterations[time_step-1,0] tempLog.append( elapsed_time ) else: elapsed_time = -1 tempLog.append('') - # give the last recorded time step - tempLog.append('%1.11f' % iterations[time_step,0]) + if iterations.shape == (0,3): + last_time_step = np.nan + else: + last_time_step = iterations[time_step-1,0] - # simulation and simulation output time - tempLog.append('%1.01f' % iterations[time_step,0]) - tempLog.append('%1.04f' % (iterations[time_step,0]/elapsed_time)) + # give the last recorded time step + tempLog.append('%1.11f' % last_time_step) + # simulation_time, as taken from cases + tempLog.append('%1.01f' % t_stop) + # real_sim_time + tempLog.append('%1.04f' % (last_time_step/elapsed_time)) tempLog.append('%1.01f' % duration) # as last element, add the total number of iterations @@ -319,10 +321,10 @@ class LogFile(object): if dt: tempLog.append('%1.7f' % dt) else: - tempLog.append('failed to find dt') + tempLog.append('nan') # number of time steps - tempLog.append('%i' % (time_step+1)) + tempLog.append('%i' % (time_step)) # if the simulation didn't end correctly, the elapsed_time doesn't # exist. Add the average and maximum nr of iterations per step @@ -1007,18 +1009,26 @@ class LoadResults(ReadHawc2): # AERO CL, CD, CM, VREL, ALFA, LIFT, DRAG, etc # Cl, R= 0.5 deg Cl of blade 1 at radius 0.49 # Azi 1 deg Azimuth of blade 1 + # NOTE THAT RADIUS FROM ch_details[ch, 0] REFERS TO THE RADIUS + # YOU ASKED FOR, AND ch_details[ch, 2] IS WHAT YOU GET, which is + # still based on a mean radius (deflections change the game) elif self.ch_details[ch, 0].split(',')[0] in ch_aero: dscr_list = self.ch_details[ch, 2].split(' ') dscr_list = misc.remove_items(dscr_list, '') - sensortype = self.ch_details[ch, 0].split(',')[0] - radius = dscr_list[-1] + # is this always valid? blade_nr = self.ch_details[ch, 2].split('blade ')[1][0] # sometimes the units for aero sensors are wrong! units = self.ch_details[ch, 1] # there is no label option + # radius what you get +# radius = dscr_list[-1] + # radius what you asked for + tmp = self.ch_details[ch, 0].split('R=') + radius = misc.remove_items(tmp, '')[-1].strip() + # and tag it tag = '%s-%s-%s' % (sensortype, blade_nr, radius) # save all info in the dict @@ -1038,6 +1048,7 @@ class LoadResults(ReadHawc2): items2 = items[1].split(' ') items2 = misc.remove_items(items2, '') azi = items2[1] + # radius what you asked for radius = items2[3] units = self.ch_details[ch, 1] # and tag it @@ -1068,13 +1079,20 @@ class LoadResults(ReadHawc2): items = misc.remove_items(items, '') coord = self.ch_details[ch, 2].split(', ')[1].strip() blade_nr = int(items[5]) - radius = float(items[8].replace(',', '')) + + # radius what you get +# radius = float(items[8].replace(',', '')) + # radius what you asked for + tmp = self.ch_details[ch, 0].split(' ') + radius = float(misc.remove_items(tmp, '')[-1]) + items = self.ch_details[ch, 0].split(',') component = items[0][-2:] units = self.ch_details[ch, 1] + # and tag it rpl = (coord, blade_nr, component, radius) - tag = 'induc-%s-blade-%1i-%s-r-%03.02f' % rpl + tag = 'induc-%s-blade-%1i-%s-r-%03.01f' % rpl # save all info in the dict channelinfo = {} channelinfo['blade_nr'] = blade_nr @@ -1103,7 +1121,13 @@ class LoadResults(ReadHawc2): blade_nr = int(tmp.split(' ')[0]) tmp = self.ch_details[ch, 2].split('radius ')[1].strip() tmp = tmp.split(',') - radius = float(tmp[0]) + + # radius what you get +# radius = float(tmp[0]) + # radius what you asked for + tmp = self.ch_details[ch, 0].split(' ') + radius = float(misc.remove_items(tmp, '')[-1]) + if len(tmp) > 1: coord = tmp[1].strip() else: @@ -1124,7 +1148,7 @@ class LoadResults(ReadHawc2): channelinfo['chi'] = ch rpl = (coord, blade_nr, sensortype, component, radius) - tag = 'aero-%s-blade-%1i-%s-%s-r-%03.02f' % rpl + tag = 'aero-%s-blade-%1i-%s-%s-r-%03.01f' % rpl # TODO: wind speed # some spaces have been trimmed here @@ -1189,12 +1213,16 @@ class LoadResults(ReadHawc2): tmp = self.ch_details[ch, 0].split(' ')[1].strip() direction = tmp.replace(',', '') blade_nr = self.ch_details[ch, 2].split('blade')[1].strip()[:2] - radius = self.ch_details[ch, 2].split('radius')[1].split(',')[0] coord = self.ch_details[ch, 2].split(',')[1].strip() - - radius = radius.strip() blade_nr = blade_nr.strip() + # radius what you get +# radius = self.ch_details[ch, 2].split('radius')[1].split(',')[0] +# radius = radius.strip() + # radius what you asked for + tmp = self.ch_details[ch, 0].split(' ') + radius = misc.remove_items(tmp, '')[-1].strip() + # and tag it rpl = (direction, blade_nr, radius, coord) tag = 'wsp-blade-%s-%s-%s-%s' % rpl -- GitLab