From 237ea8fd8b7ba1c169c7b4f41b5d53a5216c35d6 Mon Sep 17 00:00:00 2001
From: dave <dave@dtu.dk>
Date: Tue, 5 Apr 2016 18:41:24 +0200
Subject: [PATCH] prepost.Simulations: use R_eq_1hz instead of wrong
 cycle_matrix definition, add silent throughout the stack to suppress printing
 messages

---
 wetb/prepost/Simulations.py | 60 +++++++++++++++++++++----------------
 wetb/prepost/dlcdefs.py     | 16 ++++++----
 wetb/prepost/dlctemplate.py | 56 +++++++++++++++++++---------------
 wetb/prepost/misc.py        | 11 ++++---
 4 files changed, 83 insertions(+), 60 deletions(-)

diff --git a/wetb/prepost/Simulations.py b/wetb/prepost/Simulations.py
index dabfe334..164aa186 100755
--- a/wetb/prepost/Simulations.py
+++ b/wetb/prepost/Simulations.py
@@ -795,7 +795,7 @@ def prepare_launch(iter_dict, opt_tags, master, variable_tag_func,
     launch(cases, runmethod=runmethod, verbose=verbose, check_log=check_log,
            copyback_turb=copyback_turb, qsub=qsub, wine_appendix=wine_appendix,
            windows_nr_cpus=windows_nr_cpus, short_job_names=short_job_names,
-           pbs_fname_appendix=pbs_fname_appendix)
+           pbs_fname_appendix=pbs_fname_appendix, silent=silent)
 
     return cases
 
@@ -1030,10 +1030,10 @@ def launch(cases, runmethod='local', verbose=False, copyback_turb=True,
     elif runmethod in ['jess','gorm']:
         # create the pbs object
         pbs = PBS(cases, server=runmethod, short_job_names=short_job_names,
-                  pbs_fname_appendix=pbs_fname_appendix, qsub=qsub)
+                  pbs_fname_appendix=pbs_fname_appendix, qsub=qsub,
+                  verbose=verbose, silent=silent)
         pbs.wine_appendix = wine_appendix
         pbs.copyback_turb = copyback_turb
-        pbs.verbose = verbose
         pbs.pbs_out_dir = pbs_out_dir
         pbs.create()
     elif runmethod == 'local':
@@ -1851,8 +1851,8 @@ class PBS(object):
     such as the turbulence file and folder, htc folder and others
     """
 
-    def __init__(self, cases, server='gorm', qsub='time',
-                 pbs_fname_appendix=True, short_job_names=True):
+    def __init__(self, cases, server='gorm', qsub='time', silent=False,
+                 pbs_fname_appendix=True, short_job_names=True, verbose=False):
         """
         Define the settings here. This should be done outside, but how?
         In a text file, paramters list or first create the object and than set
@@ -1882,7 +1882,8 @@ class PBS(object):
 
         """
         self.server = server
-        self.verbose = True
+        self.verbose = verbose
+        self.silent = silent
 
 #        if server == 'thyra':
 #            self.maxcpu = 4
@@ -2182,7 +2183,8 @@ class PBS(object):
                 ended = True
                 # print progress:
                 replace = ((i/self.maxcpu), (i_tot/self.maxcpu), self.walltime)
-                print('pbs script %3i/%i walltime=%s' % replace)
+                if not self.silent:
+                    print('pbs script %3i/%i walltime=%s' % replace)
 
             count2 += 1
             i += 1
@@ -2196,7 +2198,8 @@ class PBS(object):
             self.ending(pbs_path)
             # progress printing
             replace = ( (i/self.maxcpu), (i_tot/self.maxcpu), self.walltime )
-            print('pbs script %3i/%i walltime=%s, partially loaded' % replace)
+            if not self.silent:
+                print('pbs script %3i/%i walltime=%s, partially loaded' % replace)
 #            print 'pbs progress, script '+format(i/self.maxcpu,'2.0f')\
 #                + '/' + format(i_tot/self.maxcpu, '2.0f') \
 #                + ' partially loaded...'
@@ -2451,7 +2454,8 @@ class PBS(object):
 
         cases_fail = {}
 
-        print('checking if all log and result files are present...', end='')
+        if not self.silent:
+            print('checking if all log and result files are present...', end='')
 
         # check for each case if we have results and a log file
         for cname, case in cases.items():
@@ -2473,7 +2477,8 @@ class PBS(object):
             if size_sel < 5 or size_dat < 5:
                 cases_fail[cname] = copy.copy(cases[cname])
 
-        print('done!')
+        if not self.silent:
+            print('done!')
 
         # length will be zero if there are no failures
         return cases_fail
@@ -3828,7 +3833,7 @@ class Cases(object):
                    save=True, m=[3, 4, 6, 8, 10, 12], neq=None, no_bins=46,
                    ch_fatigue={}, update=False, add_sensor=None,
                    chs_resultant=[], i0=0, i1=-1, saveinterval=1000,
-                   csv=True, suffix=None, fatigue_cycles=False, A=None,
+                   csv=True, suffix=None, A=None,
                    ch_wind=None, save_new_sigs=False, xlsx=False):
         """
         Calculate statistics and save them in a pandas dataframe. Save also
@@ -3851,10 +3856,6 @@ class Cases(object):
             needs to be calculated. When set to None, ch_fatigue = ch_sel,
             and hence all channels will have a fatigue analysis.
 
-        fatigue_cycles : Boolean, default=False
-            If True, the cycle matrix, or sum( n_i*S_i^m ), is calculated. If
-            set to False, the 1Hz equivalent load is calculated.
-
         chs_resultant
 
         add_sensor
@@ -4168,12 +4169,13 @@ class Cases(object):
                 signal = self.sig[:,chi]
                 if neq is None:
                     neq = float(case['[duration]'])
-                if not fatigue_cycles:
-                    eq = self.res.calc_fatigue(signal, no_bins=no_bins,
-                                               neq=neq, m=m)
-                else:
-                    eq = self.res.cycle_matrix(signal, no_bins=no_bins, m=m)
+
+                eq = self.res.calc_fatigue(signal, no_bins=no_bins,
+                                           neq=neq, m=m)
+
+                # save in the fatigue results
                 fatigue[ch_id] = {}
+                fatigue[ch_id]['neq'] = neq
                 # when calc_fatigue succeeds, we should have as many items
                 # as in m
                 if len(eq) == len(m):
@@ -4188,6 +4190,7 @@ class Cases(object):
             for m_ in m:
                 tag = 'm=%2.01f' % m_
                 tags_fatigue.append(tag)
+            tags_fatigue.append('neq')
 
             # -----------------------------------------------------------------
             # define the pandas data frame dict on first run
@@ -4408,10 +4411,10 @@ class Cases(object):
                 raise(e)
         return df_dict2
 
-    def fatigue_lifetime(self, dfs, neq, res_dir='res/', fh_lst=None, years=20.,
+    def fatigue_lifetime(self, dfs, neq_life, res_dir='res/', fh_lst=None,
                          dlc_folder="dlc%s_iec61400-1ed3/", extra_cols=[],
                          save=False, update=False, csv=False, new_sim_id=False,
-                         xlsx=False):
+                         xlsx=False, years=20.0):
         """
         Cacluate the fatigue over a selection of cases and indicate how many
         hours each case contributes to its life time.
@@ -4427,7 +4430,7 @@ class Cases(object):
             should only hold the results of one standard organized DLC (one
             turbine, one inflow case).
 
-        neq : float
+        neq_life : float
             Reference number of cycles. Usually, neq is either set to 10e6,
             10e7 or 10e8.
 
@@ -4543,12 +4546,17 @@ class Cases(object):
                 # values of the identifier columns for each case. We do this
                 # in case the original dfs holds multiple DLC cases.
                 dict_Leq[col].append(sel_sort[col].unique()[0])
+
+            # R_eq is usually expressed as the 1Hz equivalent load
+            neq_1hz = sel_sort['neq'].values
+
             for m in ms:
-                # sel_sort[m] holds the cycle_matrices for each of the DLC
+                # sel_sort[m] holds the equivalent loads for each of the DLC
                 # cases: such all the different wind speeds for dlc1.2
-                R_eq = (sel_sort[m].values*np.array(hours)).sum()
+                R_eq_mod = np.power(sel_sort[m].values, m) * neq_1hz
+                tmp = (R_eq_mod*np.array(hours)).sum()
                 # the effective Leq for each of the material constants
-                dict_Leq[m].append(math.pow(R_eq/neq, 1.0/float(m[2:])))
+                dict_Leq[m].append(math.pow(tmp/neq_life, 1.0/float(m[2:])))
                 # the following is twice as slow:
                 # [i*j for (i,j) in zip(sel_sort[m].values.tolist(),hours)]
 
diff --git a/wetb/prepost/dlcdefs.py b/wetb/prepost/dlcdefs.py
index fbfe9537..747e7753 100644
--- a/wetb/prepost/dlcdefs.py
+++ b/wetb/prepost/dlcdefs.py
@@ -240,7 +240,7 @@ def tags_defaults(master):
 
 
 def excel_stabcon(proot, fext='xlsx', pignore=None, sheet=0,
-                  pinclude=None):
+                  pinclude=None, silent=False):
     """
     Read all MS Excel files that hold load case definitions according to
     the team STABCON definitions. Save each case in a list according to the
@@ -272,16 +272,20 @@ def excel_stabcon(proot, fext='xlsx', pignore=None, sheet=0,
         first sheet (index=0) is taken.
 
     """
-    print('looking for DLC spreadsheet definitions at:')
-    print(proot)
+    if not silent:
+        print('looking for DLC spreadsheet definitions at:')
+        print(proot)
     df_list = misc.read_excel_files(proot, fext=fext, pignore=pignore,
-                                    sheet=sheet, pinclude=pinclude)
+                                    sheet=sheet, pinclude=pinclude,
+                                    silent=silent)
 
-    print('found %i Excel file(s), ' % len(df_list), end='')
+    if not silent:
+        print('found %i Excel file(s), ' % len(df_list), end='')
     k = 0
     for df in df_list:
         k += len(df)
-    print('in which a total of %s cases are defined.' % k)
+    if not silent:
+        print('in which a total of %s cases are defined.' % k)
 
     opt_tags = []
 
diff --git a/wetb/prepost/dlctemplate.py b/wetb/prepost/dlctemplate.py
index 39d1b00a..b6240f46 100755
--- a/wetb/prepost/dlctemplate.py
+++ b/wetb/prepost/dlctemplate.py
@@ -164,7 +164,7 @@ def variable_tag_func(master, case_id_short=False):
 ### PRE- POST
 # =============================================================================
 
-def launch_dlcs_excel(sim_id):
+def launch_dlcs_excel(sim_id, silent=False):
     """
     Launch load cases defined in Excel files
     """
@@ -175,9 +175,10 @@ def launch_dlcs_excel(sim_id):
     # see if a htc/DLCs dir exists
     dlcs_dir = os.path.join(P_SOURCE, 'htc', 'DLCs')
     if os.path.exists(dlcs_dir):
-        opt_tags = dlcdefs.excel_stabcon(dlcs_dir)
+        opt_tags = dlcdefs.excel_stabcon(dlcs_dir, silent=silent)
     else:
-        opt_tags = dlcdefs.excel_stabcon(os.path.join(P_SOURCE, 'htc'))
+        opt_tags = dlcdefs.excel_stabcon(os.path.join(P_SOURCE, 'htc'),
+                                         silent=silent)
 
     if len(opt_tags) < 1:
         raise ValueError('There are is not a single case defined. Make sure '
@@ -200,7 +201,8 @@ def launch_dlcs_excel(sim_id):
 #    runmethod = 'local-script'
 #    runmethod = 'windows-script'
 #    runmethod = 'jess'
-    master = master_tags(sim_id, runmethod=runmethod)
+    master = master_tags(sim_id, runmethod=runmethod, silent=silent,
+                         verbose=False)
     master.tags['[sim_id]'] = sim_id
     master.output_dirs.append('[Case folder]')
     master.output_dirs.append('[Case id.]')
@@ -219,7 +221,8 @@ def launch_dlcs_excel(sim_id):
                        write_htc=True, runmethod=runmethod, verbose=False,
                        copyback_turb=True, msg='', update_cases=False,
                        ignore_non_unique=False, run_only_new=False,
-                       pbs_fname_appendix=False, short_job_names=False)
+                       pbs_fname_appendix=False, short_job_names=False,
+                       silent=silent)
 
 
 def launch_param(sim_id):
@@ -264,10 +267,10 @@ def launch_param(sim_id):
 
 def post_launch(sim_id, statistics=True, rem_failed=True, check_logs=True,
                 force_dir=False, update=False, saveinterval=2000, csv=False,
-                fatigue_cycles=False, m=[1, 3, 4, 5, 6, 8, 10, 12, 14],
-                neq=1e6, no_bins=46, years=20.0, fatigue=True, nn_twb=1,
-                nn_twt=20, nn_blr=4, A=None, save_new_sigs=False,
-                envelopeturbine=False, envelopeblade=False, save_iter=False):
+                m=[1, 3, 4, 5, 6, 8, 10, 12, 14], neq=1e6, no_bins=46,
+                years=20.0, fatigue=True, nn_twb=1, nn_twt=20, nn_blr=4, A=None,
+                save_new_sigs=False, envelopeturbine=False, envelopeblade=False,
+                save_iter=False, AEP=False):
 
     # =========================================================================
     # check logfiles, results files, pbs output files
@@ -339,12 +342,12 @@ def post_launch(sim_id, statistics=True, rem_failed=True, check_logs=True,
         df_stats = cc.statistics(calc_mech_power=True, i0=i0, i1=i1,
                                  tags=tags, add_sensor=add, ch_fatigue=None,
                                  update=update, saveinterval=saveinterval,
-                                 suffix=suffix, fatigue_cycles=fatigue_cycles,
+                                 suffix=suffix, save_new_sigs=save_new_sigs,
                                  csv=csv, m=m, neq=neq, no_bins=no_bins,
-                                 chs_resultant=chs_resultant, A=A,
-                                 save_new_sigs=save_new_sigs)
+                                 chs_resultant=chs_resultant, A=A)
         # annual energy production
-        df_AEP = cc.AEP(df_stats, csv=csv, update=update, save=True)
+        if AEP:
+            df_AEP = cc.AEP(df_stats, csv=csv, update=update, save=True)
 
     if envelopeblade:
         ch_list = []
@@ -395,6 +398,9 @@ if __name__ == '__main__':
                         dest='stats', help='calculate statistics')
     parser.add_argument('--fatigue', action='store_true', default=False,
                         dest='fatigue', help='calculate Leq for a full DLC')
+    parser.add_argument('--AEP', action='store_true', default=False,
+                        dest='AEP', help='calculate AEP, requires '
+                        'htc/DLCs/dlc_config.xlsx')
     parser.add_argument('--csv', action='store_true', default=False,
                         dest='csv', help='Save data also as csv file')
     parser.add_argument('--years', type=float, default=20.0, action='store',
@@ -429,24 +435,26 @@ if __name__ == '__main__':
     # --plots, --report, --...
 
     # -------------------------------------------------------------------------
-#    # manually configure all the dirs
-#    p_root_remote = '/mnt/hawc2sim'
-#    p_root_local = '/home/dave/DTU/Projects/AVATAR/'
+#    # manually configure paths, HAWC2 model root path is then constructed as
+#    # p_root_remote/PROJECT/sim_id, and p_root_local/PROJECT/sim_id
+#    # adopt accordingly when you have configured your directories differently
+#    p_root_remote = '/mnt/hawc2sim/'
+#    p_root_local = '/mnt/hawc2sim/'
 #    # project name, sim_id, master file name
-#    PROJECT = 'DTU10MW'
-#    sim_id = 'C0014'
-#    MASTERFILE = 'dtu10mw_master_C0014.htc'
+#    PROJECT = 'demo'
+#    sim_id = 'A0001'
+#    MASTERFILE = 'dtu10mw_avatar_master_A0001.htc'
 #    # MODEL SOURCES, exchanche file sources
 #    P_RUN = os.path.join(p_root_remote, PROJECT, sim_id+'/')
-#    P_SOURCE = os.path.join(p_root_local, PROJECT)
+#    P_SOURCE = os.path.join(p_root_local, PROJECT, sim_id)
 #    # location of the master file
-#    P_MASTERFILE = os.path.join(p_root_local, PROJECT, 'htc', '_master/')
+#    P_MASTERFILE = os.path.join(p_root_local, PROJECT, sim_id, 'htc', '_master/')
 #    # location of the pre and post processing data
-#    POST_DIR = os.path.join(p_root_remote, PROJECT, 'python-prepost-data/')
+#    POST_DIR = os.path.join(p_root_remote, PROJECT, sim_id, 'prepost-data/')
 #    force_dir = P_RUN
 #    launch_dlcs_excel(sim_id)
 #    post_launch(sim_id, check_logs=True, update=False, force_dir=force_dir,
-#                saveinterval=2000, csv=False)
+#                saveinterval=2000, csv=True, fatigue_cycles=True, fatigue=False)
     # -------------------------------------------------------------------------
 
     # create HTC files and PBS launch scripts (*.p)
@@ -458,7 +466,7 @@ if __name__ == '__main__':
         post_launch(sim_id, check_logs=opt.check_logs, update=False,
                     force_dir=P_RUN, saveinterval=2000, csv=opt.csv,
                     statistics=opt.stats, years=opt.years, neq=opt.neq,
-                    fatigue=opt.fatigue, fatigue_cycles=True, A=opt.rotarea,
+                    fatigue=opt.fatigue, A=opt.rotarea, AEP=opt.AEP,
                     no_bins=opt.no_bins, nn_blr=opt.nn_blr, nn_twt=opt.nn_twt,
                     save_new_sigs=opt.save_new_sigs, save_iter=False,
                     envelopeturbine=opt.envelopeturbine,
diff --git a/wetb/prepost/misc.py b/wetb/prepost/misc.py
index 441e20c1..0c1ab9b0 100644
--- a/wetb/prepost/misc.py
+++ b/wetb/prepost/misc.py
@@ -678,7 +678,7 @@ def to_lower_case(proot):
             os.rename(root, new)
 
 def read_excel_files(proot, fext='xlsx', pignore=None, sheet=0,
-                     pinclude=None):
+                     pinclude=None, silent=False):
     """
     Read recursively all MS Excel files with extension "fext". Only the
     default name for the first sheet (Sheet1) of the Excel file is considered.
@@ -726,14 +726,17 @@ def read_excel_files(proot, fext='xlsx', pignore=None, sheet=0,
             # if it does contain pignore, ingore the dlc
             if pignore is not None and f_target.find(pignore) > -1:
                 continue
-            print(f_target, end='')
+            if not silent:
+                print(f_target, end='')
             try:
                 xl = pd.ExcelFile(f_target)
                 df = xl.parse(sheet)
                 df_list[f_target.replace('.'+fext, '')] = df
-                print(': sucesfully included %i case(s)' % len(df))
+                if not silent:
+                    print(': sucesfully included %i case(s)' % len(df))
             except:
-                print('     XXXXX ERROR COULD NOT READ')
+                if not silent:
+                    print('     XXXXX ERROR COULD NOT READ')
 
     return df_list
 
-- 
GitLab