1 # -*- coding: utf-8 -*-
3 # Copyright (C) 2016-2024 EDF R&D
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2.1 of the License.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the Free Software
17 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 ###############################################################################
21 ###############################################################################
23 from buildingspy.io.outputfile import Reader # To read dsres.mat
24 from os import path,getcwd,pardir,mkdir
25 from numpy import mean
31 from .functions import get_cur_time, Edit_File
33 class NotImplementedError(Exception) :
35 This exception is raised when there is only one alive (not enough to continue)
40 ###############################################################################
41 # CLASS Simulation_Files #
42 ###############################################################################
44 class Around_Simulation(object):
46 Aim: creating an efficient and user-friendly software dedicated to creating
47 initialization scripts for Modelica based simulation tools.
50 - Commentaries are written directly in the code
51 - Examples are provided with the code to make it easier to use
52 - It is recommended to create the build the list of the iteration variables from
53 the information that is displayed in the log printed by Dymola during the
54 translation (ie: choose source_list_iter_var = 'from_dymtranslog' when it is possible)
55 - The derivative of the variables are never considered as iteration variables
56 - It should be possible to create the list of the iteration variables from file
57 dslog.txt and this script gives an option to do it, but this option has never been
58 tested and may also require some modifications.
60 Required libraries that are not in the standard distribution:
64 def __init__(self,dymola_version='Unknown',curdir=getcwd(),source_list_iter_var=None,\
65 mo=None,mos=None,copy_from_dym_trans_log=None,dslog_txt=None,mat=None,\
66 iter_var_values_options=None,generated_script_options=None,alphabetical_order=True,verbose=True):
68 self.verbose = verbose #Boolean, if set to True, some informations are printed to the stdout.
70 if iter_var_values_options == None:
71 iter_var_values_options={'source':'from_mat','moment':'initial','display':False,'updated_vars':False,'GUI':'Dymola'}
73 if generated_script_options == None:
74 generated_script_options={'file_name':'Script_ini.mos','dest_dir':None,'pref':'','filters':{},'renamed':None,'compute':{}}
76 #Attributes whose values are setted without specific setters
77 self.__vdymola = dymola_version
78 self.__curdir = path.abspath(curdir)
81 self.source_list_iter_var = source_list_iter_var
82 self.mo = mo #The mo file could be used to check that no fixed value has been added to the list of the iteration variables
84 self.copy_from_dym_trans_log = copy_from_dym_trans_log
85 self.dslog_txt = dslog_txt
87 self.iter_var_values_options = iter_var_values_options
88 self.generated_script_options = generated_script_options
89 self.__alphabetical_order = alphabetical_order
90 #Attributes that cannot be given a value at the creation of the object
91 self.__not_found_iter_var = []
92 self.__not_found_complex_iter_var = []
93 self.__list_iter_var = []
94 self.__dict_iter_var = {}
95 self.__list_complex_iter_var = []
96 self.__dict_complex_iter_var = {}
97 self.__dict_iter_var_from_ini = {} # pour récupérer la valeur du fichier ini.txt
98 self.computed_variables = [] #List to store nale of variable computed by user defined function (if any)
101 ###############################################################################
103 ###############################################################################
110 return self.__vdymola
115 Directory in which the files are contained
120 def source_list_iter_var(self):
122 Type of the file in which the iteration variables will be extracted.
123 Its values is setted by set_source_list_iter_var
125 return self.__source_list_iter_var
142 def copy_from_dym_trans_log(self):
144 Path of the file which contains a copy of the text automatically
145 written by Dymola in the translation part of the log window when
146 Advanced.LogStartValuesForIteration = true.
148 return self.__copy_from_dym_trans_log
155 return self.__dslog_txt
160 Path of the mat file or list of paths of mat file
165 def not_found_iter_var(self):
167 List of the iteration variables whose values have been searched and not
170 return self.__not_found_iter_var
173 def not_found_complex_iter_var(self):
175 List of the images of complex iteration variables whose values has not
178 return self.__not_found_complex_iter_var
181 def list_iter_var(self):
183 List of the iteration variables
185 return self.__list_iter_var
188 def list_complex_iter_var(self):
190 List of iteration variables which are given the value of another variable.
191 Classic example: Tp is given the value of T0.
192 These values must be identified because the variable that is to be written
193 in the initialization script in the case of the example would be T0 and not Tp.
194 This list is included in list_iter_var
196 return self.__list_complex_iter_var
199 def dict_iter_var(self):
201 Dictionary which associates the name of an iteration variable to its value
203 return self.__dict_iter_var
206 def dict_iter_var_from_ini(self): # pour récupérer la valeur du fichier ini.txt
208 Dictionary which associates the name of an iteration variable to its value in ini.txt file
210 return self.__dict_iter_var_from_ini
213 def dict_complex_iter_var(self):
215 Dictionary that is necessary to initialize the values of the iteration
216 variables that are in list_complex_iter_var
217 Dictionary that associates the value
218 key Variable which should be given a value so that the associated
219 iteration variables are initialized
220 value Dictionary which associates
221 key Associated iteration variable
222 value Value of the associated iteration variables
224 'Tp1' is initialized with the value 'T0'
225 'Tp2' is initialized with the value 'T0'
226 dict_complex_iter_var = {'T0':{'Tp1':Tp1_value,'Tp2':Tp2_value}}
227 In the initialization script, the mean of Tp1_value and Tp2_value will be written
229 This method can only work when the list of the iteration variables has been
230 built with the text written in the log during translation (source_list_iter_var = 'from_dymtranslog')
232 return self.__dict_complex_iter_var
235 def iter_var_values_options(self):
237 Dictionary containing the options that will be used to create the dictionary
238 containing the values of the iteration variables
240 return self.__iter_var_values_options
243 def generated_script_options(self):
245 Dictionary continaing the options that will be used to generate the
248 return self.__generated_script_options
251 def alphabetical_order(self):
253 If True, the list of the iteration variables is sorted according to the
254 alphabetical order. If False, it is sorted as in the source which is used
255 to create the list of the iteration variables.
257 return self.__alphabetical_order
259 ###############################################################################
261 ###############################################################################
262 @source_list_iter_var.setter
263 def source_list_iter_var(self,source_list_iter_var):
265 Set the value of attribute source_list_iter_var.
267 Available values are:
268 'from_mos' The list is created from a .mos file
269 The mos file is supposed to be written as follows
272 'from_dymtranslog" The list is created from a .txt file which contains
273 the text automatically written by Dymola in the translation
274 part of the log window when
275 Advanced.LogStartValuesForIteration = true
276 'from_dslog' The list is created from a dslog.txt file
278 available_sources = ['from_mos','from_dymtranslog','from_dslog']
279 if source_list_iter_var == None:
280 print('No value given to self.__source_list_iter_var')
281 self.__source_list_iter_var = None
282 elif source_list_iter_var in available_sources:
283 self.__source_list_iter_var = source_list_iter_var
285 print('The chosen value for source_list_iter_var is not valid. The only valid values are\
286 from_mos, from_dymtranslog, from_dslog')
289 def mo(self,mo_file_name):
291 Set the path of the mo file
293 if mo_file_name == None:
296 self.__mo = path.join(self.curdir,mo_file_name)
299 def mos(self,mos_file_name):
301 Set the path of the mos file
303 if mos_file_name == None:
306 self.__mos = path.join(self.curdir,mos_file_name)
308 @copy_from_dym_trans_log.setter
309 def copy_from_dym_trans_log(self,copy_from_dym_trans_log):
311 Set the path of the file which contains a copy of the text automatically
312 written by Dymola in the translation part of the log window when
313 Advanced.LogStartValuesForIteration = true.
315 if copy_from_dym_trans_log == None:
316 self.__copy_from_dym_trans_log = None
318 self.__copy_from_dym_trans_log = path.join(self.curdir,copy_from_dym_trans_log)
321 def dslog_txt(self,dslog_txt):
323 Set the path of dslog.txt
325 if dslog_txt == None:
326 self.__dslog_txt = None
328 self.__dslog_txt = path.join(self.curdir,dslog_txt)
331 def mat(self,mat_file_name):
333 Set the path of the mat file
335 if not(isinstance(mat_file_name,list)):
336 if mat_file_name == None:
339 self.__mat = [path.join(self.curdir,mat_file_name)]
342 for mat_file_name_elem in mat_file_name:
343 self.__mat.append(path.join(self.curdir,mat_file_name_elem))
346 @iter_var_values_options.setter
347 def iter_var_values_options(self,iter_var_values_options):
349 Set the value of attribute iter_var_values_options.
350 This attribute has to be a dictionary conataining the following keys:
352 Available values for source are "from_mat" and "from_mos"
354 Available values for moment are "initial" and "final"
356 Available values for display are False and True
357 updated_vars (optional)
358 Available values for updated_vars are False and True
360 iter_var_values_options_base = {'source':'from_mat','moment':'initial','display':False,'updated_vars':False,'GUI':'Dymola'}
362 for key in list(iter_var_values_options_base.keys()):
364 iter_var_values_options_base[key] = iter_var_values_options[key]
367 print('Default value used for generated_script_options[\''+str(key)+'\']')
369 iter_var_values_options_base['updated_vars'] = iter_var_values_options_base['updated_vars'] and iter_var_values_options_base['display'] #Comparison is only possible if the file is changed on the fly
372 for key in list(iter_var_values_options.keys()):
373 if not key in list(iter_var_values_options_base.keys()):
374 print('iter_var_values_options[\''+str(key)+'\'] will not be used: only the following keys are allowed:')
375 for ki in iter_var_values_options_base.keys() :
378 print('iter_var_values_options should be a dictionary')
380 self.__iter_var_values_options = iter_var_values_options_base
382 @generated_script_options.setter
383 def generated_script_options(self,generated_script_options):
384 #Default value. It garantees that the structure will always be the same
385 generated_script_options_base={'file_name':'Script_ini.mos','dest_dir':None,'pref':'','filters':{},'renamed':None,'compute':{}}
387 for key in list(generated_script_options_base.keys()):
389 generated_script_options_base[key] = generated_script_options[key]
392 print('Default value used for generated_script_options[\''+str(key)+'\']')
395 for key in list(generated_script_options.keys()):
396 if not key in list(generated_script_options_base.keys()):
397 print('generated_script_options[\''+str(key)+'\'] will not be used:only values associated to "file_name", "dest_dir", "pref", "filters", "compute" and "renamed" can be taken into account')
400 print('generated_script_options should be a dictionary')
402 self.__generated_script_options = generated_script_options_base
403 ###############################################################################
405 ###############################################################################
407 def reset_list_iter_var(self):
409 Reset the value of attributes list_iter_var and list_complex_iter_var
411 self.__list_iter_var = []
412 self.__list_complex_iter_var = []
414 def reset_not_found_iter_var(self):
416 Reset the value of attributes not_found_iter_var and not_found_images_of_complex_iter_var
418 self.__not_found_iter_var = []
419 self.__not_found_complex_iter_var = []
421 ###############################################################################
423 ###############################################################################
425 def set_list_iter_var(self):
427 Set the value of attribute list_iter_var, which contains the list of the iteration variables.
428 This list can be created from
429 - file dslog.txt (created in case of a translation error) - to be used carefully
430 - a .mos file that contains the iteration variables
431 - a .txt file that contains the text written by Dymola if option
432 Advanced.LogStartValuesForIteration is activated (text written in
433 the translation part of the log window)
435 This method will look for the iteration variables in a source defined by
436 self.source_list_iter_var.
438 self.reset_list_iter_var()
440 if self.source_list_iter_var == 'from_mos':
442 #Regular expression to find the interesting lines - be careful: it does not return the whole line
443 input_line_regex = re.compile(r'^[^\\][A-Za-z0-9_.[\]\s]+=\s*-?[0-9]+')
445 with open(self.mos,"r") as lines:
447 if input_line_regex.search(line):
448 words = [word.strip() for word in line.split('=')]
449 #Add the name of the current iteration variable to the list of iteration variables
450 self.list_iter_var.append(words[0])
451 self.__dict_iter_var_from_ini[words[0]] = words[1] # valeur du .mos brute_init
453 #Only option that can handle the iteration variables that are given the value of other variables
454 elif self.source_list_iter_var == 'from_dymtranslog':
455 if self.iter_var_values_options['updated_vars'] :
456 old_list = self.dymtranslog_read(oldlist=True)
457 if self.iter_var_values_options['display'] : #If required, open the 'ini.txt' file to allow modifications (copy)
458 #file_display = Popen("Notepad " + self.copy_from_dym_trans_log)
460 Edit_File(self.copy_from_dym_trans_log)
461 self.dymtranslog_read()
462 if self.iter_var_values_options['updated_vars'] :
463 print('Exiting variables: %s' % ' ,'.join(set(old_list).difference(self.list_iter_var)))
464 print('Entering variables: %s' % ' ,'.join(set(self.list_iter_var).difference(old_list)))
466 elif self.source_list_iter_var == 'from_dslog':
467 if self.iter_var_values_options['GUI'] == 'OM' :
468 raise NotImplementedError("Automatic reading of the log is still not implemented for OpenModelica") from None
469 input_line_regex = re.compile(r'^[^\\][A-Za-z0-9_.[\]\s]+=\s*-?[0-9]+')
471 with open(self.dslog_txt,'r') as lines:
473 if ('Last value of the solution:' in line) or ('Last values of solution vector' in line):
475 elif ('Last value of the solution:' in line) or ('Last values of solution vector' in line):
477 if read and input_line_regex.search(line):
478 words = [word.strip() for word in line.split('=')]
479 #Add the name of the current iteration variable to the list of iteration variables
480 self.list_iter_var.append(words[0])
481 self.__dict_iter_var_from_ini[words[0]] = words[1] # valeur du dslog.txt brute_init
483 exit('Option given to method set_list_iter_var is not defined. \n\
484 Available options are "from_mos", "from_dymtranslog" and "from_dslog".')
487 if self.alphabetical_order:
488 self.list_iter_var.sort()
490 def dymtranslog_read(self,oldlist=False):
492 Method dedicated to the dymtranslog reading
497 out = self.list_iter_var
498 #Regular expression to find the interesting lines
499 var_and_start_regex = re.compile(r'[A-Za-z]+[A-Za-z0-9_.[,\s\]]*')
500 with open(self.copy_from_dym_trans_log,'r') as lines:
502 if ('=' in line) and not ('der(' == line[0:4] or 'der (' == line[0:5]) : #Should be a mathematical expression; then, no derivative.
504 tmp_words = var_and_start_regex.findall(line)
505 words = [word.strip() for word in tmp_words]
507 #Elimination of start
509 del words[words.index('start')]
510 except ValueError : #The line does not contain "start" word : this line does not talk about initialization variable -> skip
512 del words[words.index('each start')]
516 if self.iter_var_values_options['GUI'] == 'OM' :
517 del words[words.index('nominal')] #Added for OpenModelica
519 #If 'E' appears in the right part of a line, it should not be considered as a variable name
520 #because it is almost certainly the 'E' of the scientific writing
521 #Do not call 'E' any of your variable!!
522 if any(s in words[1:] for s in ['E','e']) :
525 words.pop(words.index('E'))
527 words.pop(words.index('e')) #Added for OpenModelica
530 #Add the name of the current iteration variable to the list of iteration variables
531 if self.iter_var_values_options['GUI'] == 'OM' :
532 out.append(words[0].split(' ',1)[1]) #OpenModelica : Errors lines copied from the compilation log contains the 'unit' as first word (Integer, Real...)
533 else: #Dymola, default case
535 self.__dict_iter_var_from_ini[words[0]] =[word.strip() for word in line.split('=')][1][:-1] # valeur du ini.txt brute_init
538 #Detection of the iteration variables that are given the values of other variables
539 if not(oldlist) and len(words) >1:
540 self.list_complex_iter_var.append(words[0])
541 self.dict_complex_iter_var[words[1]] = {words[0]:None}
545 def set_dict_iter_var(self):
547 Set the value of attribute dict_iter_var (and not_found_iter_var).
548 dict_iter_var contains the values of the iteration variables that should
549 be given to Dymola to help the simulation to initialize.
550 These values can be found in a .mat file (containing the result of a simulation)
551 or in a .mos file (which has been constructed either manually or automatically).
553 This method will use the source specified in self.iter_var_values_options['source']
554 to find the values of the iteration variables. It will use the final value of each
555 variable if self.iter_var_values_options['source']== 'final' and the initial
556 value of each variable if self.iter_var_values_options['source']== 'initial'
558 self.iter_var_values_options is a dictionary whose entries must be the following ones:
559 'source' (compulsory)
564 'moment' (compulsory if the value associated to key 'source' is 'from_mat')
575 pref = self.generated_script_options['pref']
577 #Reset the list of the iteration variables that have not been found
578 self.reset_not_found_iter_var()
580 #Create a dictionary to store the intermediate variable values to handle
581 #the iteration variables that are given values of other variables
582 dict_intermediate_values = {}
584 #Get value of filters
585 filters = self.generated_script_options['filters']
587 if self.iter_var_values_options['source'] == 'from_mat':#It is recommended to use this option
589 #Start or final value to be taken from the mat file
590 if self.iter_var_values_options['moment'] == 'initial':
592 elif self.iter_var_values_options['moment'] == 'final':
595 exit("'moment' option can be set only to 'initial' or 'final'")
597 # Read file .mat which contains simulation results
598 var_to_drop = [] #Because of array expansion
599 for mat_file in self.mat:
600 structData = Reader(mat_file,'dymola')
602 for name_var in self.list_iter_var:
603 varTmp = None #Initialisation
604 res_name_var = name_var
607 if name_var[:len(pref)] == pref:
608 #+1 because of the '.' that is next to pref
609 res_name_var = name_var[len(pref)+1:]
611 # Only if pref is not used (conservative, even if not necessary...)
612 elif not(self.generated_script_options['renamed'] is None):
613 for newname in self.generated_script_options['renamed'].keys() : #For each of renamed component
614 if res_name_var.startswith(newname) : #Check whether the new name in the dictionary matches the current variable
615 res_name_var = self.generated_script_options['renamed'][newname] + res_name_var[len(newname):] #Substitute the new name with the old one (who has to be looked for in the .mat file)
617 for cur_filter in filters:
618 #If the end of the variable name is in list(filters.keys()) -> ex: h_vol,
619 #the corresponding part of the variable is replaced by filers[key] -> ex:h.
620 #The value which will be looked for will therefore be module1.h if the iteration
621 #variable is module1.h_vol. In the script, the name of the iteration variable
622 #(module1.h_vol) will also be given the value calculated for module1.h
623 if cur_filter == name_var[-len(cur_filter):]:
624 res_name_var = res_name_var[:-len(cur_filter)]+filters[cur_filter]
627 varTmp = structData.values(res_name_var)[1][mom]
628 except KeyError: #The variable is not found
631 node_pos = re.search("\[\d+\]",res_name_var).span() #Position of the node number if any (in case the error is due to a remesh of the model)
632 except AttributeError: #No node number found
635 node_pos = re.search("\[\]",res_name_var).span() #Position of empty brakets (all array values are due)
636 except AttributeError :
639 if res_name_var != name_var :
640 print('Filters and prefixes still have to be implemented for arrays of unknown size')
642 print(f'{name_var}: unknown size -> Taking all values in .mat (if any)')
643 tmp = f'{res_name_var[:node_pos[0]]}\[\d\{res_name_var[node_pos[0]+1:]}'
644 expanded_vars = structData.varNames(tmp)
645 for tmp_var in expanded_vars :
646 self.__dict_iter_var[tmp_var] = structData.values(tmp_var)[1][mom]
648 var_to_drop.append(name_var)
651 else: #If a node number is found
652 name_start = res_name_var[:node_pos[0]+1]
653 name_end = res_name_var[node_pos[1]-1:]
654 node = int(res_name_var[node_pos[0]+1:node_pos[1]-1]) #Requested node
655 for ii in range(node):
657 varTmp = structData.values(name_start + str(node-ii-1) + name_end)[1][mom] #Look for an upstream node
662 if varTmp is None : #If varTmp not defined (name_var not found, not due to remesh)
664 for var,f in self.generated_script_options['compute'].items() :
665 if res_name_var.endswith(var) :
666 #Collect function inputs
667 root = res_name_var[:-len(var)] #Root path of the variable
669 for k,v in f['f_inputs'].items() :
670 f_inputs[k] = structData.values(root+v)[1][mom]
671 varTmp = f['user_f'](f_inputs)
672 self.computed_variables.append(name_var)
674 if varTmp is None : #If varTmp not defined (name_var not found, not due to remesh, not computed)
675 self.not_found_iter_var.append(name_var)
678 #Retrieve the initialization value from the .mat
679 if name_var in self.list_complex_iter_var:
680 dict_intermediate_values[name_var] = varTmp
682 self.__dict_iter_var[name_var] = varTmp
684 for image_of_complex_var in list(self.dict_complex_iter_var.keys()):
685 for complex_iter_var in list(self.dict_complex_iter_var[image_of_complex_var].keys()):
687 self.dict_complex_iter_var[image_of_complex_var][complex_iter_var] = dict_intermediate_values[complex_iter_var]
688 except:#In case the value of variable complex_iter_var has not been found in the mat file
689 if complex_iter_var not in self.not_found_complex_iter_var:
690 self.not_found_complex_iter_var.append(complex_iter_var)
694 for i in var_to_drop :
695 self.list_iter_var.remove(i)
697 elif self.iter_var_values_options['source'] == 'from_mos':
698 #Regular expression to find the interesting lines - be careful: it does not return the whole line
699 input_line_regex = re.compile(r'^[^\\][A-Za-z0-9_.[\]\s]+=\s*-?[0-9]+')
700 value_regex = re.compile(r'[0-9e+-.]*')
702 with open(self.mos,'r') as lines:
704 if input_line_regex.search(line):
705 words = [word.strip() for word in line.split("=")]
707 if pref+name_var in self.list_iter_var:
708 #The following lines eliminates spaces, ;, and other non-numerical elements
709 value = float(value_regex.findall(words[1])[0])
710 #Add the name of the current iteration variable to the list of iteration variables
711 self.__dict_iter_var[name_var] = value
713 #All the iteration variables in self.list_iter_var are added to self.not_found_iter_var if their value has not been found
714 for name_var in self.list_iter_var:
715 if not name_var in self.dict_iter_var:
716 self.not_found_iter_var.append(name_var)
719 print('Option given to method set_list_iter_var is not defined. \n\
720 Available options are "from_mat" and "from_mos".')
722 #Sort the not found iteration variables lists
723 #Warning: these sorting method puts all the variables whose first letter
724 #is uppercase before the variables whose first letter is lowercase.
725 self.not_found_iter_var.sort()
726 self.not_found_complex_iter_var.sort()
729 def create_script_ini(self):
731 Create a .mos initialization script.
732 The list of the iteration variables must have been created before using this method
733 with set_list_iter_var. The values of the iteration variables must have been found
734 before using this method with set_dict_iter_var.
735 This whole process can be done in one single step with method create_quickly_script_ini.
737 self.generated_script_options is a dictionary whose entries must be the following ones:
739 Name of the .mos file that will be generated
741 path of the directory in which the file should be saved
743 pref + '.' will be added at the beginning of all variables.
744 It is useful if a model has been inserted in a module of a new model
746 Modifications that have to be applied to the names of the iteration variables
747 Example: {'h_vol':'h'} -> the variable whose name finishes by h_vol will be given the value of the variable whose name finishes by h. Be careful with the use of this filter
749 #Put the values of self.generated_script_options in short varaibles to make it easier to write the following function
750 file_name,dest_dir = self.generated_script_options['file_name'],self.generated_script_options['dest_dir']
754 dest_file_path = path.join(dest_dir,file_name)
756 with open(dest_file_path,'w') as output:
757 output.write('///////////////////////////////////////////////////////////////////\n')
758 output.write('// Script automatically generated by Python ')
760 #Date of the creation of the file
761 output.write('on '+get_cur_time()+'\n')
764 output.write('// Dymola version: '+self.vdymola+'\n')
766 #Source of the list of iteration variables
767 output.write('// List of the iteration variables from file ')
768 if self.source_list_iter_var == 'from_mos':
769 output.write(self.mos+'\n')
770 elif self.source_list_iter_var == 'from_dymtranslog':
771 output.write(self.copy_from_dym_trans_log+'\n')
772 elif self.source_list_iter_var == 'from_dslog':
773 output.write(self.dslog_txt+'\n')
775 #Source of the values of the iteration variables
776 output.write('// Values of the iteration variables from file ')
777 if self.iter_var_values_options['source'] == 'from_mos':
778 output.write(self.mos+'\n')
779 elif self.iter_var_values_options['source'] == 'from_mat':
780 output.write(self.mat[0]+'\n') #The name of the first mat file is kept if several are given
781 output.write('///////////////////////////////////////////////////////////////////\n\n\n')
783 #Iteration variables whose values have not been found
784 if len(self.not_found_iter_var) > 0:
785 output.write('///////////////////////////////////////////////////////////////////\n')
786 output.write('// Iteration variables whose values have not been found:\n')
787 for var_name in self.not_found_iter_var:
788 if var_name not in self.not_found_complex_iter_var:
789 output.write('// '+var_name+'\n')
790 output.write('///////////////////////////////////////////////////////////////////\n\n')
792 #Iteration variables whose values have not been found
793 if len(self.not_found_complex_iter_var) > 0:
794 output.write('///////////////////////////////////////////////////////////////////\n')
795 output.write('// Complex iteration variables whose values have not been found:\n')
796 for var_name in self.not_found_complex_iter_var:
797 output.write('// '+var_name+'\n')
799 #Explain the user which values he should give to which variables
800 output.write('//It would have no effect to give these complex variables a value in an initialization script.\n')
801 output.write('//The initialization should be done by giving the following values to the following variables:\n')
802 for complex_iter_var in self.not_found_complex_iter_var:
803 for image_of_complex_iter_var in list(self.dict_complex_iter_var.keys()):
804 if complex_iter_var in list(self.dict_complex_iter_var[image_of_complex_iter_var].keys()):
805 current_iter_vars = list(self.dict_complex_iter_var[image_of_complex_iter_var].keys())
806 output.write('//'+image_of_complex_iter_var+' should be given the mean of the following variables:\n')
807 for cur_var in current_iter_vars:
808 output.write('//- '+cur_var+'\n')
809 output.write('///////////////////////////////////////////////////////////////////\n\n')
811 #Values of the iteration variables
812 output.write('// Iteration variables values:\n')
813 #for var_name in self.__list_iter_var:
814 #Appending the additional elements to the end of the list
815 tmp_not_originally_present = set(self.__list_iter_var) ^ set(self.__dict_iter_var.keys())
816 print(f'Variables from expansion: {tmp_not_originally_present}')
817 tmp_list = self.__list_iter_var + list(tmp_not_originally_present)
818 for var_name in tmp_list :
819 if not var_name in self.not_found_iter_var:
820 if not var_name in self.list_complex_iter_var:
821 cmp_str = '' if var_name not in self.computed_variables else '\t//Computed by user defined function'
822 var_value = self.__dict_iter_var[var_name]
823 output.write(var_name.ljust(40)+'\t\t=\t\t'+str(var_value)+';'+cmp_str+'\n')
825 #Variables that are given the value of other variables
826 if len(list(self.dict_complex_iter_var.keys())) > 0:
828 print("WARNING: Some of the initialising values depends on model's parameters values : automatic changes are unsafe!")
829 print("WARNING: However, some proposals based on previous results are wrote to the script, but commented.")
830 print("WARNING: If required to successfully initialize, the user is invited to check the proposed values and, potentially, uncomment them.")
831 output.write('\n// Complex iteration variables values:\n')
832 output.write('// WARNING: Some of the following variables may be key parameters of your model.\n')
833 output.write('// WARNING: To change their values automatically may be dangerous since it may change the model itself.\n')
834 output.write('// WARNING: That is why the following lines are disabled (commented) by default.\n')
835 output.write('// WARNING: However, some of them may be initialization parameters (Tstart, ...) and may be safely set.\n')
836 output.write('// WARNING: In this case, if you still have initialisation issues, you can safely change their values (uncomment the lines).\n\n')
837 for var_name in list(self.dict_complex_iter_var.keys()):
838 #Get the list of values associated to var_name
839 intermediate_list = [self.dict_complex_iter_var[var_name][key] for key in list(self.dict_complex_iter_var[var_name].keys())]
840 #Eliminate values None
841 intermediate_list2 = [elem for elem in intermediate_list if elem != None]
842 #If the list contains at least one value
843 if intermediate_list2 != []:
844 #The mean of the values of the list is calculated
845 var_value = mean([elem for elem in intermediate_list if elem != None])
846 #The mean value is written in the initialization script
847 #Check if any of the values is computed by user function
848 computed = [i for i in intermediate_list if i in self.computed_variables]
849 cmp_str = '' if not computed else '\t//Computed by user defined function'
850 output.write('//'+var_name.ljust(40)+'\t\t=\t\t'+str(var_value)+';'+cmp_str+'\n')
852 def create_quickly_script_ini(self):
855 - looks for the list of iteration variables with set_list_iter_var;
856 - looks for the values of the iteration variables with set_dict_iter_var;
857 - crearte a initialization script with create_script_ini.
860 self.set_list_iter_var()
861 self.set_dict_iter_var()
862 self.create_script_ini()
864 if __name__ == '__main__':
865 print('\n AUTODIAGNOSTIC\n ==============\n')