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 from os import path,getcwd,rename,remove,replace
24 This class has been written to change dsin.txt (a file that is generated by
25 Dymola and that contains the values of the parameters of a simulation). Changing
26 the values of parameters in dsin.txt lets the user launch a different simulation.
27 This can also be done with method modelicares.exps.write_params.
28 The present class has been written in case in order to make it possible to
29 change the parameters values in dsin.txt without importing modelicares.
31 New features introduced 02/2019:
32 - possibility of change a dsin.txt type file having a different name
33 - by default, the previous use of this module should remain unchanged
35 New features introduced 09/2022:
36 - script adapted to the situations in which the variables are described on
37 a single line (instead of 2 traditionnally) in the dsin file
40 def __init__(self,dict_inputs,filedir=path.abspath(getcwd()),dsin_name='dsin.txt',old_file_name='dsin_old.txt',new_file_name='dsin.txt'):
41 self.__dict_inputs = dict_inputs.copy() #this way the dictionary is not emptied
42 self.__filedir = filedir
43 self.__dsin_name = dsin_name
44 self.__old_file_name = old_file_name
45 self.__new_file_name = new_file_name
46 self.__maybe_par_dict = {}
49 def dict_inputs(self):
51 Dictionary associating to each variable whose value has to be given to
52 dsin.txt (inputs + iteration variables if necessary) its value.
54 return self.__dict_inputs
59 Name of the dsin.txt file to change, it might have a different name
61 return self.__dsin_name
64 def maybe_par_dict(self):
66 List of variables to be changed which are not identified as 'parameter' in the dsin.txt.
68 return self.__maybe_par_dict
73 Path of the directory in which the file dsin.txt is located.
74 The new version of this file will also be saved in this directory.
79 def old_file_name(self):
81 The original file dsin.txt that is modified is saved under a name that can be chosen.
82 dsin_old.txt seems appropriate
84 return self.__old_file_name
87 def new_file_name(self):
89 The new version of dsin.txt is given a name that can be chosen through
90 this attribute. In order to be able to launch a simulation, this name has
93 return self.__new_file_name
95 ########################################################################
97 ########################################################################
98 def write_in_dsin(self):
100 Main method of this class.
101 This method creates a new dsin.txt file.
102 The original file is renamed 'dsin_old.txt'.
103 The new file is named 'dsin.txt'
105 #reading has value 1 while the part of the file currently being
106 #read is the part of the file in which the variables are given
107 #values. Only this part of the file has to be changed in order
108 #to change the parameters values.
110 in_line1,in_line2=None,None
111 with open(path.join(self.filedir,self.dsin_name),'r') as lines:
112 with open(path.join(self.filedir,'dsin_tmp.txt'),'w') as output:
114 if reading==1 and len(line)>1 and not line[0] == '#':
122 if 'initialValue' in line:
124 #If the structure of file dsin.txt generated by
125 #Dymola was changed, the following line could have
127 if '# Matrix with 6 columns' in line:
130 # - START - Take into account the possibility of handling dsin.txt files with one single line for describin variables
131 if in_line1 != None and len(in_line1.split())>4 and reading==1: #Case where there is one line per parameter rather than two in the dsin file
133 line_list = in_line1.split() #The variable name may contain spaces...
134 valtype1,val,elem13,elem14,valtype2,elem16,elem17 = line_list[0],line_list[1],line_list[2],line_list[3],line_list[4],line_list[5],line_list[6]
137 for reste in line_list[7:]:
140 if var in self.dict_inputs.keys():
141 val = self.dict_inputs[var]
142 #The format is not the same depending on the length of some variables
143 if len(str(val))<=7 and len(elem14)<=7:
144 txt ='{elem11:>3} {elem12:>7} {elem13:>18} {elem14:>7} {elem15:>18} {elem16:>5} {elem17:>3} {elem18:<}\n'
145 if len(str(val))<=7 and len(elem14)>7:
146 txt ='{elem11:>3} {elem12:>7} {elem13:>18} {elem14:>23} {elem15:>2} {elem16:>5} {elem17:>3} {elem18:<}\n'
147 if len(str(val))>7 and len(elem14)<=7:
148 txt ='{elem11:>3} {elem12:>23} {elem13:>2} {elem14:>7} {elem15:>18} {elem16:>5} {elem17:>3} {elem18:<}\n'
149 if len(str(val))>7 and len(elem14)>7:
150 txt ='{elem11:>3} {elem12:>23} {elem13:>2} {elem14:>23} {elem15:>2} {elem16:>5} {elem17:>3} {elem18:<}\n'
152 out_line = txt.format(elem11=valtype1,elem12=val,elem13=elem13,elem14=elem14,elem15=valtype2,elem16=elem16,elem17=elem17,elem18=var)
154 if valtype1 != '-1' or (valtype2 != '1' and valtype2 != '2') : #(0,6) combination looks like the only case to look into
155 self.__maybe_par_dict[var] = val
156 self.__dict_inputs.pop(var) #Deleting the variable from the list of 'to do'
161 output.write(out_line)
164 # - END - Take into account the possibility of handling dsin.txt files with one single line for describin variables
167 elif in_line2 != None:
168 valtype1,val,elem13,elem14 = in_line1.split()
169 #valtype2,elem22,elem23,var = in_line2.split()
170 line2_list = in_line2.split() #The variable name may contain spaces...
171 valtype2 = line2_list[0]
173 for reste in line2_list[3:]:
176 if var in self.dict_inputs.keys():
177 val = self.dict_inputs[var]
178 out_line1 = '{elem11:>3} {elem12:>23} {elem13:23} {elem14:>23}\n'.format(elem11=valtype1,elem12=val,elem13=elem13,elem14=elem14)
179 if valtype1 != '-1' or (valtype2 != '1' and valtype2 != '2') : #(0,6) combination looks like the only case to look into
180 self.__maybe_par_dict[var] = val
181 self.__dict_inputs.pop(var) #Deleting the variable from the list of 'to do'
186 output.write(out_line1)
187 output.write(out_line2)
189 in_line1,in_line2=None,None
191 # rename(path.join(self.filedir,'dsin.txt'),path.join(self.filedir,self.old_file_name))
192 replace(path.join(self.filedir,self.dsin_name),path.join(self.filedir,self.old_file_name)) # resolve the conflit with old version
194 if len(self.dict_inputs) > 0 : #At least one variable was not changed
195 remove(path.join(self.filedir,'dsin_tmp.txt'))
196 raise KeyError("The following variables were not found in dsin.txt:\n %s" % list(self.dict_inputs.keys()))
198 rename(path.join(self.filedir,'dsin_tmp.txt'),path.join(self.filedir,self.new_file_name))
200 if __name__ == '__main__':
201 print('\n AUTODIAGNOSTIC\n ==============\n')