1 """
2 Application-class that implements pyFoamPrepareCase.py
3 """
4 from optparse import OptionGroup
5
6 from .PyFoamApplication import PyFoamApplication
7
8 from PyFoam.RunDictionary.SolutionDirectory import SolutionDirectory
9 from PyFoam.Basics.Utilities import rmtree,copytree,execute,remove
10 from PyFoam.RunDictionary.ParsedParameterFile import ParsedParameterFile,WriteParameterFile
11 from PyFoam.Basics.TemplateFile import TemplateFile
12 from PyFoam.Execution.BasicRunner import BasicRunner
13
14 from .CommonTemplateFormat import CommonTemplateFormat
15 from .CommonTemplateBehaviour import CommonTemplateBehaviour
16
17 from PyFoam.ThirdParty.six import print_,iteritems
18
19 from PyFoam import configuration
20
21 from os import path,listdir
22
23 -class PrepareCase(PyFoamApplication,
24 CommonTemplateBehaviour,
25 CommonTemplateFormat):
26
27 parameterOutFile="PyFoamPrepareCaseParameters"
28
29 - def __init__(self,
30 args=None,
31 **kwargs):
32 self.defaultMeshCreate=configuration().get("PrepareCase","MeshCreateScript")
33 self.defaultCaseSetup=configuration().get("PrepareCase","CaseSetupScript")
34
35 description="""\
36 Prepares a case for running. This is intended to be the replacement for
37 boiler-plate scripts. The steps done are
38 1. Clear old data from the case (including processor directories)
39 2. if a folder 0.org is present remove the 0 folder too
40 3. go through all folders and for every found file with the extension .template
41 do template expansion using the pyratemp-engine (automatically create variables
42 casePath and caseName)
43 4. create a mesh (either by using a script or if a blockMeshDict is present by
44 running blockMesh. If none of these is present assume that there is a valid mesh
45 present)
46 5. copy every foo.org that is found to to foo (recursively if directory)
47 6. do template-expansion for every file with the extension .postTemplate
48 7. execute another preparation script
49
50 The used parameters are written to a file 'PyFoamPrepareCaseParameters' and are used by other utilities
51 """
52 PyFoamApplication.__init__(self,
53 args=args,
54 description=description,
55 usage="%prog <caseDirectory>",
56 interspersed=True,
57 nr=1,
58 exactNr=True,
59 **kwargs)
60
62 output=OptionGroup(self.parser,
63 "Output",
64 "What information should be given")
65 self.parser.add_option_group(output)
66 output.add_option("--fatal",
67 action="store_true",
68 dest="fatal",
69 default=False,
70 help="If non-cases are specified the program should abort")
71 output.add_option("--silent",
72 action="store_true",
73 dest="silent",
74 default=False,
75 help="Don't complain about non-case-files")
76 output.add_option("--quiet",
77 action="store_false",
78 dest="verbose",
79 default=True,
80 help="Do not report what is being done")
81 output.add_option("--no-write-parameters",
82 action="store_false",
83 dest="writeParameters",
84 default=True,
85 help="Usually a file '"+self.parameterOutFile+"' with a dictionary of the used parameters is written to the case directory. ")
86
87 extensions=OptionGroup(self.parser,
88 "Extensions",
89 "File extensions that are used in actions")
90 self.parser.add_option_group(extensions)
91 extensions.add_option("--template-extension",
92 action="store",
93 dest="templateExt",
94 default=".template",
95 help="Extension for template files. Default: %default")
96 extensions.add_option("--post-template-extension",
97 action="store",
98 dest="postTemplateExt",
99 default=".postTemplate",
100 help="Extension for post-template files. Default: %default")
101 extensions.add_option("--original-extension",
102 action="store",
103 dest="originalExt",
104 default=".org",
105 help="Extension for files and directories that are copied. Default: %default")
106
107 inputs=OptionGroup(self.parser,
108 "Inputs",
109 "Inputs for the templating process")
110 self.parser.add_option_group(inputs)
111
112 inputs.add_option("--parameter-file",
113 action="append",
114 default=[],
115 dest="valuesDicts",
116 help="Name of a dictionary-file in OpenFOAM-format. Can be specified more than once. Values in later files override old values")
117 inputs.add_option("--values-string",
118 action="append",
119 default=[],
120 dest="values",
121 help="String with the values that are to be inserted into the template as a dictionaty in Python-format. Can be specified more than once and overrides values from the parameter-files")
122
123 special=OptionGroup(self.parser,
124 "Special files and directories",
125 "Files and directories that get special treatment")
126 self.parser.add_option_group(special)
127
128 special.add_option("--directories-to-clean",
129 action="append",
130 default=["0"],
131 dest="cleanDirectories",
132 help="Directory from which templates are cleaned (to avoid problems with decomposePar). Can be specified more than once. Default: %default")
133
134 CommonTemplateFormat.addOptions(self)
135 CommonTemplateBehaviour.addOptions(self)
136
137 stages=OptionGroup(self.parser,
138 "Stages",
139 "Which steps should be executed")
140 self.parser.add_option_group(stages)
141
142 stages.add_option("--only-variables",
143 action="store_true",
144 dest="onlyVariables",
145 default=False,
146 help="Do nothing. Only read the variables")
147
148 stages.add_option("--no-clear",
149 action="store_false",
150 dest="doClear",
151 default=True,
152 help="Do not clear the case")
153
154 stages.add_option("--no-templates",
155 action="store_false",
156 dest="doTemplates",
157 default=True,
158 help="Do not rework the templates")
159
160 stages.add_option("--no-mesh-create",
161 action="store_false",
162 dest="doMeshCreate",
163 default=True,
164 help="Do not execute a script to create a mesh")
165
166 stages.add_option("--no-copy",
167 action="store_false",
168 dest="doCopy",
169 default=True,
170 help="Do not copy original directories")
171
172 stages.add_option("--no-post-templates",
173 action="store_false",
174 dest="doPostTemplates",
175 default=True,
176 help="Do not rework the post-templates")
177
178 stages.add_option("--no-case-setup",
179 action="store_false",
180 dest="doCaseSetup",
181 default=True,
182 help="Do not execute a script to set initial conditions etc")
183
184 stages.add_option("--no-template-clean",
185 action="store_false",
186 dest="doTemplateClean",
187 default=True,
188 help="Do not clean template files from 0-directory")
189
190 scripts=OptionGroup(self.parser,
191 "Scripts",
192 "Specification of scripts to be executed")
193 self.parser.add_option_group(scripts)
194
195 scripts.add_option("--mesh-create-script",
196 action="store",
197 dest="meshCreateScript",
198 default=None,
199 help="Script that is executed after the template expansion to create the mesh. If not specified then the utility looks for "+self.defaultMeshCreate+" and executes this. If this is also not found blockMesh is executed if a blockMeshDict is found")
200 scripts.add_option("--case-setup-script",
201 action="store",
202 dest="caseSetupScript",
203 default=None,
204 help="Script that is executed after the original files have been copied to set initial conditions or similar. If not specified then the utility looks for "+self.defaultCaseSetup+" and executes this.")
205
207 """Go recursivly through directories and copy foo.org to foo"""
208 if self.opts.verbose:
209 print_("Looking for originals in",startDir)
210 for f in listdir(startDir):
211 if f[0]==".":
212 if self.opts.verbose:
213 print_("Skipping",f)
214 continue
215 src=path.join(startDir,f)
216 if path.splitext(f)[1]==self.opts.originalExt:
217 dst=path.join(startDir,path.splitext(f)[0])
218 if path.exists(dst):
219 if self.opts.verbose:
220 print_("Replacing",dst,"with",src)
221 rmtree(dst)
222 else:
223 if self.opts.verbose:
224 print_("Copying",src,"to",dst)
225 copytree(src,dst,force=True)
226 elif path.isdir(src):
227 self.copyOriginals(src)
228
232 """Go recursivly through directories and remove all files that have a specific extension"""
233 if self.opts.verbose:
234 print_("Looking for extension",ext,"in",startDir)
235 for f in listdir(startDir):
236 if f[0]==".":
237 if self.opts.verbose:
238 print_("Skipping",f)
239 continue
240 src=path.join(startDir,f)
241 if path.splitext(f)[1]==ext and not path.isdir(src):
242 if self.opts.verbose:
243 print_("Removing",src)
244 remove(src)
245 elif path.isdir(src):
246 self.cleanExtension(src,ext)
247
252 """Go through the directory recursively and replate foo.template with
253 foo after inserting the values"""
254 if self.opts.verbose:
255 print_("Looking for templates with extension",templateExt,"in ",startDir)
256 for f in listdir(startDir):
257 if f[0]==".":
258 if self.opts.verbose:
259 print_("Skipping",f)
260 continue
261 if path.isdir(path.join(startDir,f)):
262 self.searchAndReplaceTemplates(
263 path.join(startDir,f),
264 values,
265 templateExt)
266 elif path.splitext(f)[1]==templateExt:
267 fName=path.join(startDir,path.splitext(f)[0])
268 if self.opts.verbose:
269 print_("Found template for",fName)
270 t=TemplateFile(name=fName+templateExt,
271 tolerantRender=self.opts.tolerantRender,
272 allowExec=self.opts.allowExec,
273 expressionDelimiter=self.opts.expressionDelimiter,
274 assignmentLineStart=self.opts.assignmentLineStart)
275 t.writeToFile(fName,values)
277 cName=self.parser.getArgs()[0]
278 if self.checkCase(cName,fatal=self.opts.fatal,verbose=not self.opts.silent):
279 self.addLocalConfig(cName)
280 sol=SolutionDirectory(cName,archive=None,paraviewLink=False)
281
282 if self.opts.onlyVariables:
283 self.opts.verbose=True
284
285 vals={}
286 vals["casePath"]='"'+path.abspath(cName)+'"'
287 vals["caseName"]='"'+path.basename(path.abspath(cName))+'"'
288
289 if self.opts.verbose:
290 print_("Looking for template values",cName)
291 for f in self.opts.valuesDicts:
292 if self.opts.verbose:
293 print_("Reading values from",f)
294 vals.update(ParsedParameterFile(f,
295 noHeader=True,
296 doMacroExpansion=True).getValueDict())
297 for v in self.opts.values:
298 if self.opts.verbose:
299 print_("Updating values",v)
300 vals.update(eval(v))
301
302 if self.opts.verbose and len(vals)>0:
303 print_("\nUsed values\n")
304 nameLen=max(len("Name"),
305 max(*[len(k) for k in vals.keys()]))
306 format="%%%ds - %%s" % nameLen
307 print_(format % ("Name","Value"))
308 print_("-"*40)
309 for k,v in sorted(iteritems(vals)):
310 print_(format % (k,v))
311 print_("")
312 elif self.opts.verbose:
313 print_("\nNo values specified\n")
314
315 if self.opts.onlyVariables:
316 return
317
318 if self.opts.doClear:
319 if self.opts.verbose:
320 print_("Clearing",cName)
321 sol.clear(processor=True,
322 pyfoam=True,
323 vtk=True,
324 removeAnalyzed=True,
325 keepParallel=False,
326 clearHistory=False,
327 clearParameters=True,
328 additional=["postProcessing"])
329
330 if self.opts.writeParameters:
331 fName=path.join(cName,self.parameterOutFile)
332 if self.opts.verbose:
333 print_("Writing parameters to",fName)
334 with WriteParameterFile(fName,noHeader=True) as w:
335 w.content.update(vals,toString=True)
336 w.writeFile()
337
338 self.addToCaseLog(cName)
339
340 zeroOrig=path.join(sol.name,"0.org")
341
342 hasOrig=path.exists(zeroOrig)
343 if not hasOrig:
344 if self.opts.verbose:
345 print_("Not going to clean '0'")
346 self.opts.cleanDirectories.remove("0")
347
348 if self.opts.doCopy:
349 if hasOrig:
350 if self.opts.verbose:
351 print_("Found 0.org. Clearing 0")
352 zeroDir=path.join(sol.name,"0")
353 if path.exists(zeroDir):
354 rmtree(zeroDir)
355 elif self.opts.verbose:
356 print_("No 0-directory")
357
358 if self.opts.verbose:
359 print_("")
360
361 if self.opts.doTemplates:
362 self.searchAndReplaceTemplates(sol.name,
363 vals,
364 self.opts.templateExt)
365
366 if self.opts.verbose:
367 print_("")
368
369 if self.opts.doMeshCreate:
370 if self.opts.meshCreateScript:
371 scriptName=path.join(sol.name,self.opts.meshCreateScript)
372 if not path.exists(scriptName):
373 self.error("Script",scriptName,"does not exist")
374 elif path.exists(path.join(sol.name,self.defaultMeshCreate)):
375 scriptName=path.join(sol.name,self.defaultMeshCreate)
376 else:
377 scriptName=None
378
379 if scriptName:
380 if self.opts.verbose:
381 print_("Executing",scriptName,"for mesh creation")
382 if self.opts.verbose:
383 echo="Mesh: "
384 else:
385 echo=None
386 result="".join(execute([scriptName],workdir=sol.name,echo=echo))
387 open(scriptName+".log","w").write(result)
388 else:
389 if self.opts.verbose:
390 print_("No script for mesh creation found. Looking for 'blockMeshDict'")
391 if sol.blockMesh()!="":
392 if self.opts.verbose:
393 print_(sol.blockMesh(),"found. Executing 'blockMesh'")
394 bm=BasicRunner(argv=["blockMesh","-case",sol.name])
395 bm.start()
396 if not bm.runOK():
397 self.error("Problem with blockMesh")
398 if self.opts.verbose:
399 print_("")
400
401 if self.opts.doCopy:
402 self.copyOriginals(sol.name)
403
404 if self.opts.verbose:
405 print_("")
406
407 if self.opts.doPostTemplates:
408 self.searchAndReplaceTemplates(sol.name,
409 vals,
410 self.opts.postTemplateExt)
411
412 if self.opts.verbose:
413 print_("")
414
415 if self.opts.doCaseSetup:
416 if self.opts.caseSetupScript:
417 scriptName=path.join(sol.name,self.opts.caseSetupScript)
418 if not path.exists(scriptName):
419 self.error("Script",scriptName,"does not exist")
420 elif path.exists(path.join(sol.name,self.defaultCaseSetup)):
421 scriptName=path.join(sol.name,self.defaultCaseSetup)
422 else:
423 scriptName=None
424
425 if scriptName:
426 if self.opts.verbose:
427 print_("Executing",scriptName,"for case setup")
428 if self.opts.verbose:
429 echo="Case:"
430 else:
431 echo=None
432 result="".join(execute([scriptName],workdir=sol.name,echo=echo))
433 open(scriptName+".log","w").write(result)
434 else:
435 if self.opts.verbose:
436 print_("No script for case-setup found. Nothing done")
437 if self.opts.verbose:
438 print_("")
439
440 if self.opts.doTemplateClean:
441 if self.opts.verbose:
442 print_("Clearing templates")
443 for d in self.opts.cleanDirectories:
444 for e in [self.opts.templateExt,self.opts.postTemplateExt]:
445 self.cleanExtension(path.join(sol.name,d),e)
446 if self.opts.verbose:
447 print_("")
448
449 if self.opts.verbose:
450 print_("Case setup finished")
451