-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdoe_batch.py
More file actions
184 lines (173 loc) · 7.27 KB
/
doe_batch.py
File metadata and controls
184 lines (173 loc) · 7.27 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import shutil
import os
import glob
import time
import joblib
import subprocess
from utils.modeling import *
from utils.sampling import *
from recurdyn import *
from GlobalVariables import GlobVar
from . import initialize, dispose
def RunDOE_Batch(
ModelFileDir: str = f"{os.getcwd()}/SampleModel.rdyn",
TopFolderName: str = "TestDOE_GUI",
NumCPUCores: int = 8,
EndTime: float = 1.0,
NumSteps: int = 100,
NumParallelBatches: int = 3,
NumBatRunsOnThisPC: int = None,
) -> None:
application, model_document, plot_document, model = initialize()
application.ClearMessage()
assert type(NumSteps) == int, "NumSteps must be integer."
assert NumCPUCores in [
0,
1,
2,
4,
8,
16,
], "NumCPUCores must be one of 0,1,2,4,8,16."
model_document = application.OpenModelDocument(ModelFileDir)
modelPath = model_document.GetPath(PathType.WorkingFolder)
model = model_document.Model
application.Settings.CreateOutputFolder = False
model_document.UseOutputFileName = True
model_document.ModelProperty.DynamicAnalysisProperty.SimulationStep.Value = NumSteps
model_document.ModelProperty.DynamicAnalysisProperty.SimulationTime.Value = EndTime
model_document.ModelProperty.DynamicAnalysisProperty.MatchSolvingStepSize = True
model_document.ModelProperty.DynamicAnalysisProperty.MatchSimulationEndTime = True
if NumCPUCores:
application.Settings.AutoCoreNumber = False
application.Settings.CoreNumber = NumCPUCores
else:
application.Settings.AutoCoreNumber = True
application.ClearMessage()
if NumBatRunsOnThisPC is None:
NumBatRunsOnThisPC = NumParallelBatches
AnalysisStartTime = time.perf_counter()
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
Counter = 1
SamplePV = np.logspace(-2, 10, 10, endpoint=True)
for samplepv in SamplePV:
ChangePVvalue(model, "PV_SampleK", samplepv)
SubFolderName = f"{TopFolderName}_{Counter:04d}"
ExportSolverFiles(
TopFolderName, SubFolderName, EndTime=EndTime, NumSteps=NumSteps
)
Counter += 1
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
######################################### EDIT HERE #########################################
batfilespath = WriteBatch(TopFolderName, NumParallelBatches)
run = joblib.Parallel(n_jobs=NumBatRunsOnThisPC)(
joblib.delayed(RunSubprocess)(bat) for bat in batfilespath[:NumBatRunsOnThisPC]
)
AnalysisEndTime = time.perf_counter()
s = AnalysisEndTime - AnalysisStartTime
print(f"Analysis finished within {s:.2f}sec.")
def ExportSolverFiles(
OutputFolderName: str,
OutputFileName: str,
EndTime: int = 1,
NumSteps: int = 101,
PlotMultiplierStepFactor: int = 1,
):
"""
Exports *.rmd, *.rss, and copies *.(DependentExt) to directory modelPath/OutputFolderName/*.* for batch automated solving.
DependentExt may include tire files (*.tir), GRoad files (*.rdf), or flexible meshes.
:param OutputFolderName:
:param OutputFileName:
:param EndTime: Simulation end time
:param NumSteps: Simulation steps
:param PlotMultiplierStepFactor:
:return:
"""
application, model_document, plot_document, model = initialize()
model_document = application.ActiveModelDocument
model = model_document.Model
modelPath = model_document.GetPath(PathType.WorkingFolder)
print(f"{modelPath}{OutputFolderName}\\{OutputFileName}")
os.makedirs(f"{modelPath}{OutputFolderName}\\{OutputFileName}", exist_ok=True)
# Copy dependency files
DependentExt = (
"tir",
"rdf",
)
DependentFiles = []
for ext in DependentExt:
DependentFiles.extend(glob.glob(f"{modelPath}*.{ext}"))
for file in DependentFiles:
shutil.copy(file, f"{modelPath}{OutputFolderName}\\{OutputFileName}")
# Analysis Property
model_document.ModelProperty.DynamicAnalysisProperty.MatchSolvingStepSize = True
model_document.ModelProperty.DynamicAnalysisProperty.MatchSimulationEndTime = True
model_document.ModelProperty.DynamicAnalysisProperty.PlotMultiplierStepFactor.Value = (
PlotMultiplierStepFactor
)
# RMD export
model_document.FileExport(
f"{modelPath}{OutputFolderName}\\{OutputFileName}\\{OutputFileName}.rmd", True
)
# RSS export
RSScontents = f"SIM/DYN, END = {EndTime}, STEP = {NumSteps}\nSTOP"
rss = open(
f"{modelPath}{OutputFolderName}\\{OutputFileName}\\{OutputFileName}.rss", "w"
)
rss.write(RSScontents)
rss.close()
def WriteBatch(SolverFilesFolderName: str, parallelBatches: 1):
"""
Write *.bat execution files for batch solving.
:param SolverFilesFolderName:
:param parallelBatches:
:return:
"""
application, model_document, plot_document, model = initialize()
application.ClearMessage()
model_document = application.ActiveModelDocument
model = model_document.Model
modelPath = model_document.GetPath(PathType.WorkingFolder)
RMDlist = glob.glob(
f"{modelPath}{SolverFilesFolderName}\\**\\*.rmd", recursive=True
)
batfilespath = []
for i in range(parallelBatches):
BatchFileName = f"{SolverFilesFolderName}_{i + 1}.bat"
interval = round(len(RMDlist) / parallelBatches)
bat = open(f"{modelPath}{SolverFilesFolderName}\\{BatchFileName}", "w")
if i == parallelBatches - 1: # Last index
idx_start = i * interval
idx_end = len(RMDlist)
else:
idx_start = i * interval
idx_end = (i + 1) * interval
for rmdName in RMDlist[idx_start:idx_end]:
solverfilename = os.path.basename(rmdName).split(".")[:-1]
if len(os.path.basename(rmdName).split(".")) > 2:
solverfilename = ".".join(os.path.basename(rmdName).split(".")[:-1])
else:
solverfilename = "".join(solverfilename)
BATcontent = []
BATcontent.append(modelPath[:2]) # Drive Name
BATcontent.append(f"cd {os.path.dirname(rmdName)}") # cd RMD path
BATcontent.append(
f"{GlobVar.rdSolverDir} {solverfilename} {solverfilename}"
) #
bat.writelines(line + "\n" for line in BATcontent)
bat.close()
application.PrintMessage(
f"Created batch executable {modelPath}{SolverFilesFolderName}\\{BatchFileName}"
)
print(
f"Created batch executable {modelPath}{SolverFilesFolderName}\\{BatchFileName}"
)
batfilespath.append(f"{modelPath}{SolverFilesFolderName}\\{BatchFileName}")
return batfilespath
def RunSubprocess(single_batfilepath):
subprocess.run(single_batfilepath, creationflags=subprocess.CREATE_NEW_CONSOLE)