我目前正在开发一个Petrel
插件,我需要运行一个模拟案例(通过“For循环”),我创建我的案例运行器,导出它并运行它.. 。)在完成模拟并关闭控制台后,我检查CaseRunner.IsRunning
属性并显示true
!这导致结果未加载到海燕系统。
我尝试在完成案例的Run
之后手动加载结果(使用caserunner
并在我的代码中使用批处理文件)并且我在编程环境中看不到任何结果。
有没有人能解决这种情况? 这是我的代码的相关部分:
Case theCase = arguments.TheCase;
Case Test2 = simroots.CreateCase(theCase, "FinalCase");
CaseRunner cRunners = SimulationSystem.GetCaseRunner(Test2);
cRunners.Export();
cRunners.Run();
bool b = cRunners.IsRunning;
实际上我在进程结束时检查了;在“cRunners.Run”之后,代码等待退出流程:
System.Diagnostics.Process[] parray = System.Diagnostics.Process.GetProcesses();
foreach (System.Diagnostics.Process pr in parray)
{
if (pr.ProcessName == "cmd")
{
pr.WaitForExit();//just wait
}
}
当控制台自行关闭时,我检查了cRunners.IsRunning术语。 但是,我不是那么专家......你能告诉我一个使用CaseRunnerMonitor的例子吗?派生类的定义及其实现。
我尝试了一些不同的场景来获得我想要的结果,我在这里放了一些 首先,我创建了我的CaseRunnerMonitor类:
public class MyMonitor : CaseRunnerMonitor
{
//…
public override void RunCompleted()
{
// define arguments
foreach (Slb.Ocean.Petrel.DomainObject.Simulation.SummaryResult sr in simroot.SummaryResults)
{
IEnumerable ….
List ….
// some codes to change the input arguments according to the current step simulation summary results
}
PetrelLogger.InfoOutputWindow("MyMonitor is completed!");
}
//…
}
然后使用它:
private void button1_Click(object sender, EventArgs e)
{
// Some codes that define some arguments…
for (int j = 0; j < 8; j++)
{
// some changes in the arguments
Case MyTest;
MyMonitor monit4 = new MyMonitor();
SimulationRoot simroot = SimulationRoot.Get(PetrelProject.PrimaryProject);
using (ITransaction trans = DataManager.NewTransaction())
{
trans.Lock(simroot);
MyTest = simroot.CreateCase(OriginalCase, MycaseNameFunc());
trans.Commit();
}
CaseRunner cRun = SimulationSystem.GetCaseRunner(MyTest);
cRun.Export();
cRun.Run(monit4);
//Wait(); //waits for current process to close
}
}
但问题是MyTest案例结果部分在我的运行完成后是空的。在这种情况下,当第8次(最后一次)模拟完成时,所有结果都加载到海燕。如果我没有激活Wait()函数,那么所有8次运行几乎都是同时调用...
我改变了我的场景,每次运行后我的回调都是读取模拟结果,改变一些东西并调用下一次运行 我创建了我的CaseRunnerMonitor类:
public class MyMonitor2 : CaseRunnerMonitor
{
//…
public override void RunCompleted()
{
// define arguments
index++;
if (index <=8)
{
foreach (Slb.Ocean.Petrel.DomainObject.Simulation.SummaryResult sr in simroot.SummaryResults)
{
IEnumerable ….
List ….
// some codes to change the input arguments according to the current step simulation summary results
}
Case MyTest;
MyMonitor monit4 = new MyMonitor();
SimulationRoot simroot = SimulationRoot.Get(PetrelProject.PrimaryProject);
using (ITransaction trans = DataManager.NewTransaction())
{
trans.Lock(simroot);
MyTest = simroot.CreateCase(OriginalCase, MycaseNameFunc());
trans.Commit();
}
CaseRunner cRun = SimulationSystem.GetCaseRunner(MyTest);
cRun.Export();
cRun.Run(monit4);
}
PetrelLogger.InfoOutputWindow("MyMonitor2 is completed!");
}
//…
}
然后使用它:
private void button1_Click(object sender, EventArgs e)
{
Index=0;
// Some codes that define some arguments…
// some changes in the arguments
Case MyTest;
MyMonitor monit5 = new MyMonitor();
SimulationRoot simroot = SimulationRoot.Get(PetrelProject.PrimaryProject);
using (ITransaction trans = DataManager.NewTransaction())
{
trans.Lock(simroot);
MyTest = simroot.CreateCase(OriginalCase, MycaseNameFunc());
trans.Commit();
}
CaseRunner cRun = SimulationSystem.GetCaseRunner(MyTest);
cRun.Export();
cRun.Run(monit5);
}
在这种情况下不需要wait()函数。但问题是我在当前运行完成之前在一个级别访问MyTest案例结果。即,当运行6完成时,我可以通过MyTest.Results查看第5步结果,而第6步结果是空的,尽管运行完成。
答案 0 :(得分:0)
我检查了
CaseRunner.IsRunning
属性,并显示true
这是因为Caserunner.Run()是非阻塞的;也就是说,它启动另一个线程来启动运行。控制流然后立即传递到您的cRunners.IsRunning
检查,这在模拟正在进行时是正确的。
cRunners.Run(); //non-blocking
bool b = cRunners.IsRunning;
如果您想在模拟完成时进行回叫,则应该查看CaseRunnerMonitor
。
编辑:
你能告诉我一个使用CaseRunnerMonitor的例子吗?派生类的定义及其实现。
创建您的监视器类:
public class CustomCaseRunnerMonitor : CaseRunnerMonitor
{
//...
public override void RunCompleted()
{
//This is probably the callback you want
}
}
使用它:
Case myCase = WellKnownSimulators.ECLIPSE100.CreateSimulationCase(...);
CaseRunner runner = SimulationSystem.GetCaseRunner(myCase);
var myMonitor = new CustomCaseRunnerMonitor(...);
runner.Run(myMonitor);
//Your callbacks defined in your CustomCaseRunnerMonitor will now be called
另见&#34;运行和监控模拟&#34;在SimulationSystem API文档中。
答案 1 :(得分:0)
啊,好的。我没有意识到你正试图用CaseMonitor加载结果。
我担心简短的回答是&#34;不,你不能知道Petrel加载结果的时间&#34;。
如果在Case参数中设置了选项,那么Petrel会自动加载结果。 (定义模拟案例 - &gt;前进 - &gt;自动加载结果)。
在API中:
EclipseFormatSimulator.Arguments args = EclipseFormatSimulator.GetEclipseFormatSimulatorArguments(myCase);
EclipseFormatSimulator.Arguments.RuntimeArguments runtimeArgs = args.Runtime;
runtimeArgs.AutoLoadResults = true;
runtimeArgs.AutoLoadResultsInterval = 120; //How frequently in seconds Petrel polls sim dir.
在案例结束后,您必须轮询SimulationRoot.SummaryResults(使用您已使用的相同API)。
您应该使用我们讨论过的CaseRunnerMonitor来确定何时开始这样做,而不是您目前拥有的System.Diagnostics.Process[] parray = System.Diagnostics.Process.GetProcesses();
代码。