Geant4 VMC Version 6.7
Loading...
Searching...
No Matches
TG4RunManager.cxx
Go to the documentation of this file.
1//------------------------------------------------
2// The Geant4 Virtual Monte Carlo package
3// Copyright (C) 2007 - 2015 Ivana Hrivnacova
4// All rights reserved.
5//
6// For the licensing terms see geant4_vmc/LICENSE.
7// Contact: root-vmc@cern.ch
8//-------------------------------------------------
9
14
15#include "TG4RunManager.h"
17#include "TG4DetConstruction.h"
18#include "TG4EventAction.h"
19#include "TG4G3PhysicsManager.h"
20#include "TG4GeometryManager.h"
21#include "TG4GeometryServices.h"
22#include "TG4Globals.h"
23#include "TG4PhysicsManager.h"
25#include "TG4RegionsManager.h"
26#include "TG4RegionsManager2.h"
27#include "TG4RunConfiguration.h"
28#include "TG4SDConstruction.h"
29#include "TG4SDManager.h"
30#include "TG4SDServices.h"
32#include "TG4StackPopper.h"
33#include "TG4StateManager.h"
34#include "TG4StepManager.h"
35#include "TG4SteppingAction.h"
36#include "TG4TrackManager.h"
37#include "TG4TrackingAction.h"
39
40#include <G4Threading.hh>
41#include <G4Types.hh>
42#ifdef G4MULTITHREADED
43#include <G4MTRunManager.hh>
44#else
45#include <G4RunManager.hh>
46#endif
47
48#include <G4ScoringManager.hh>
49#include <G4VScoringMesh.hh>
50
51#include <G4UIExecutive.hh>
52#include <G4UImanager.hh>
53#include <G4UIsession.hh>
54#include <G4Version.hh>
55#include <Randomize.hh>
56
57
58#ifdef USE_G4ROOT
59#include <TG4RootNavMgr.h>
60#endif
61
62#include <TGeoManager.h>
63#include <TInterpreter.h>
64#include <TMCManager.h>
65#include <TMCManagerStack.h>
66#include <TROOT.h>
67#include <TRandom.h>
68#include <TRint.h>
69#include <TVirtualMC.h>
70#include <TVirtualMCApplication.h>
71
72namespace
73{
74
75TG4EventAction* GetEventAction()
76{
77 return dynamic_cast<TG4EventAction*>(const_cast<G4UserEventAction*>(
78 G4RunManager::GetRunManager()->GetUserEventAction()));
79}
80
81} // namespace
82
83//_____________________________________________________________________________
86
87//_____________________________________________________________________________
89 TG4RunConfiguration* runConfiguration, int argc, char** argv)
90 : TG4Verbose("runManager"),
91 fRunManager(0),
92 fMessenger(this),
93 fRunConfiguration(runConfiguration),
97 fRootUIOwner(false),
98 fARGC(argc),
99 fARGV(argv),
100 fUseRootRandom(true),
101 fIsMCStackCached(false),
104 fInProcessRun(false)
105{
107
108 if (VerboseLevel() > 1) {
109 G4cout << "TG4RunManager::TG4RunManager " << this << G4endl;
110 }
111
112 if (fgInstance) {
113 TG4Globals::Exception("TG4RunManager", "TG4RunManager",
114 "Cannot create two instances of singleton.");
115 }
116
117 if (!fRunConfiguration) {
118 TG4Globals::Exception("TG4RunManager", "TG4RunManager",
119 "Cannot create instance without runConfiguration.");
120 }
121
122 fgInstance = this;
123
124 // Define fARGV, fARGC if not provided
125 if (fARGC == 0) {
126 fARGC = 1;
127 fARGV = (char**)new char*[fARGC];
128 fARGV[0] = StrDup("undefined");
129 }
130
131 G4bool isMaster = !G4Threading::IsWorkerThread();
132
133 if (isMaster) {
134 fgMasterInstance = this;
135
136 // create and configure G4 run manager
138
139 if (runConfiguration->IsUseOfG4Scoring()) {
140 // activate G4 command-line scoring
141 G4ScoringManager::GetScoringManager();
142 }
143 }
144 else {
145 // Get G4 worker run manager
146 fRunManager = G4RunManager::GetRunManager();
147
148 // Clone G4Root navigator if needed
150
151 fRegionsManager = fgMasterInstance->fRegionsManager;
152 fRootUISession = fgMasterInstance->fRootUISession;
153 fGeantUISession = fgMasterInstance->fGeantUISession;
154 }
155
156 if (VerboseLevel() > 1) {
157 G4cout << "TG4RunManager has been created." << this << G4endl;
158 }
159}
160
161//_____________________________________________________________________________
163{
165
166 G4bool isMaster = !G4Threading::IsWorkerThread();
167
168 if (isMaster) {
169 delete fRunConfiguration;
170 delete fRegionsManager;
171 delete fGeantUISession;
172 delete fRunManager;
173 if (fRootUIOwner) delete fRootUISession;
175 }
176 fgInstance = 0;
177}
178
179//
180// private methods
181//
182
183//_____________________________________________________________________________
185{
188
189 // Geometry construction and navigator
190 //
191 if (VerboseLevel() > 1)
192 G4cout << "TG4RunManager::ConfigureRunManager " << this << G4endl;
193
194 TString userGeometry = fRunConfiguration->GetUserGeometry();
195
197 fRunConfiguration->CreateUserRegionConstruction());
198
200 fRunConfiguration->CreateUserPostDetConstruction());
201
202 // Root navigator
203#ifdef USE_G4ROOT
204 TG4RootNavMgr* rootNavMgr = 0;
205 if (userGeometry == "VMCtoRoot" || userGeometry == "Root") {
206 if (!TMCManager::Instance()) {
207
208#if ROOT_VERSION_CODE >= ROOT_VERSION(6, 22, 8)
209 // Set Root default units to TGeo
210 TGeoManager::LockDefaultUnits(false);
211 TGeoManager::SetDefaultUnits(TGeoManager::kRootUnits);
212 TGeoManager::LockDefaultUnits(true);
213#endif
214
215 // Construct geometry via VMC application
217 G4cout << "Running TVirtualMCApplication::ConstructGeometry"
218 << std::endl;
219
221 TVirtualMCApplication::Instance()->ConstructGeometry();
223
224 // Set top volume and close Root geometry if not yet done
225 if (!gGeoManager->IsClosed()) {
226 TGeoVolume* top = (TGeoVolume*)gGeoManager->GetListOfVolumes()->First();
227 gGeoManager->SetTopVolume(top);
228 gGeoManager->CloseGeometry();
229 }
230
231 // Now that we have the ideal geometry, call application misalignment code
233 TVirtualMCApplication::Instance()->MisalignGeometry();
235 }
236 // Pass geometry to G4Root navigator
237 rootNavMgr = TG4RootNavMgr::GetInstance(gGeoManager);
238 }
239#endif
240
241 // G4 run manager
242#ifdef G4MULTITHREADED
243 if (fRunConfiguration->IsMTApplication()) {
244 fRunManager = new G4MTRunManager();
245 fRunManager->SetUserInitialization(new TG4WorkerInitialization());
246 }
247 else {
248 fRunManager = new G4RunManager();
249 }
250#else
251 fRunManager = new G4RunManager();
252#endif
253 if (VerboseLevel() > 1) {
254 G4cout << "G4RunManager has been created." << G4endl;
255 }
256
257 if (userGeometry != "VMCtoRoot" && userGeometry != "Root") {
258 fRunManager->SetUserInitialization(
259 fRunConfiguration->CreateDetectorConstruction());
260 if (VerboseLevel() > 1)
261 G4cout << "CreateDetectorConstruction done." << G4endl;
262 }
263 else {
264#ifdef USE_G4ROOT
265 G4int nthreads = 1;
266#ifdef G4MULTITHREADED
267 if (fRunConfiguration->IsMTApplication()) {
268 nthreads = G4MTRunManager::GetMasterRunManager()->GetNumberOfThreads();
269 }
270#endif
271 rootNavMgr->Initialize(new TG4PostDetConstruction(), nthreads);
272 rootNavMgr->ConnectToG4();
273#else
274 TG4Globals::Exception("TG4RunManager", "ConfigureRunManager",
275 "geomVMCtoRoot and geomRoot options require Geant4 VMC built with "
276 "G4Root.");
277#endif
278 }
279
280 // Other mandatory classes
281 //
282 fRunManager->SetUserInitialization(fRunConfiguration->CreatePhysicsList());
283 if (VerboseLevel() > 1) G4cout << "CreatePhysicsList done." << G4endl;
284
285 // User fast simulation
286 TG4VUserFastSimulation* userFastSimulation =
287 fRunConfiguration->CreateUserFastSimulation();
288 if (userFastSimulation) {
291 userFastSimulation);
292 }
293 else {
294 TG4Globals::Warning("TG4RunManager", "ConfigureRunManager",
295 "TG4SpecialPhysicsList must be instantiated to use fast simulation");
296 }
297 }
298
299 fRunManager->SetUserInitialization(
301 if (VerboseLevel() > 1)
302 G4cout << "Create ActionInitialization done." << G4endl;
303
304 // Regions manager
305 //
306 if (fRunConfiguration->IsSpecialCuts()) {
307 if (fRunConfiguration->IsSpecialCutsOld()) {
309 }
310 else {
312 }
313 }
314
315 if (VerboseLevel() > 1)
316 G4cout << "TG4RunManager::ConfigureRunManager done " << this << G4endl;
317}
318
319//_____________________________________________________________________________
321{
322 // Clone Root navigator for worker thread
323 //
324#ifdef USE_G4ROOT
325 TString userGeometry = fRunConfiguration->GetUserGeometry();
326 if (userGeometry != "VMCtoRoot" && userGeometry != "Root") return;
327
328 if (VerboseLevel() > 1)
329 G4cout << "TG4RunManager::CloneRootNavigatorForWorker " << this << G4endl;
330
331 // Master Root navigator
332 TG4RootNavMgr* masterRootNavMgr = TG4RootNavMgr::GetMasterInstance();
333
334 // Create G4Root navigator on worker
335 TG4RootNavMgr* rootNavMgr = TG4RootNavMgr::GetInstance(*masterRootNavMgr);
336 if (VerboseLevel() > 1)
337 G4cout << "TG4RootNavMgr has been created." << rootNavMgr << G4endl;
338
339 // rootNavMgr->Initialize(new TG4PostDetConstruction());
340 rootNavMgr->ConnectToG4();
341
342 if (VerboseLevel() > 1)
343 G4cout << "TG4RunManager::CloneRootNavigatorForWorker done " << this
344 << G4endl;
345#endif
346}
347
348//_____________________________________________________________________________
350{
352
353 // get Root UI session if it exists
354 fRootUISession = gROOT->GetApplication();
355 if (fRootUISession) {
356 fARGC = fRootUISession->Argc();
357 delete[] fARGV;
358 fARGV = fRootUISession->Argv();
359 }
360
361 // filter out "-splash" from argument list
362 FilterARGV("-splash");
363
364 // create root UI if it does not exist
365 if (!fRootUISession) {
366 // copy only first command line argument (name of program)
367 // (use the same way as in TApplication.cxx)
368 char** argv = 0;
369 if (fARGC > 0) {
370 argv = (char**)new char*[fARGC];
371 }
372
373 // copy command line arguments, can be later accessed via Argc() and Argv()
374 for (int i = 0; i < fARGC; i++) {
375 argv[i] = StrDup(fARGV[i]);
376 }
377
378 fRootUISession = new TRint("rootSession", &fARGC, argv, 0, 0);
379 fRootUIOwner = true;
380 }
381}
382
383//_____________________________________________________________________________
384void TG4RunManager::FilterARGV(const G4String& arg)
385{
388
389 if (fARGC <= 1) return;
390
391 G4bool isArg = false;
392 for (G4int i = 0; i < fARGC; i++) {
393 if (G4String(fARGV[i]) == arg) isArg = true;
394 if (isArg && i + 1 < fARGC) fARGV[i] = fARGV[i + 1];
395 }
396
397 if (isArg) fARGC--;
398}
399
400//_____________________________________________________________________________
402{
405
406 long seeds[10];
407 seeds[0] = gRandom->GetSeed();
408 seeds[1] = gRandom->GetSeed();
409 seeds[2] = 0;
410 CLHEP::HepRandom::setTheSeeds(seeds);
411}
412
413// public methods
414
415//_____________________________________________________________________________
417{
419
420 if (VerboseLevel() > 1)
421 G4cout << "TG4RunManager::Initialize " << this << G4endl;
422
423 // create G4RunManager
424 // ConfigureRunManager();
425
426#if G4VERSION_NUMBER == 1100
427 // Temporary work-around for bug in Cerenkov in Geant4 11.0
428 TG4PhysicsManager::Instance()->StoreCerenkovMaxBetaChangeValue();
429#endif
430
431 // initialize Geant4
432 fRunManager->Initialize();
433
434 // finish geometry
436
437 // initialize SD manager
438 // TG4SDManager::Instance()->Initialize();
439
440 if (VerboseLevel() > 1)
441 G4cout << "TG4RunManager::Initialize done " << this << G4endl;
442}
443
444//_____________________________________________________________________________
446{
449
450 if (VerboseLevel() > 1)
451 G4cout << "TG4RunManager::LateInitialize " << this << G4endl;
452
453 G4bool isMaster = !G4Threading::IsWorkerThread();
454
455 // define particles
457
458 // set user limits
459 if (isMaster) {
461 *TG4G3PhysicsManager::Instance()->GetCutVector(),
462 *TG4G3PhysicsManager::Instance()->GetControlVector());
463
464 // pass info if cut on e+e- pair is activated to stepping action
465 // TO DO LATER - Stepping Action NOT AVAILABLE
466 //((TG4SteppingAction*)fRunManager->GetUserSteppingAction())
467 // ->SetIsPairCut((*TG4G3PhysicsManager::Instance()->GetIsCutVector())[kEplus]);
468
469 // convert tracking cuts in range cuts per regions
470 if (fRunConfiguration->IsSpecialCuts()) {
471 fRegionsManager->DefineRegions();
472 fRegionsManager->UpdateProductionCutsTable();
473 }
474 }
475
476 // activate/inactivate physics processes
479
480 // late initialize step manager
482
483 // late initialize action classes
484 if (GetEventAction()) {
485 GetEventAction()->LateInitialize();
488 }
489
490 // print statistics
493
494 if (VerboseLevel() > 2) {
496 }
497
498 // set the random number seed
500
501 if (VerboseLevel() > 1)
502 G4cout << "TG4RunManager::LateInitialize done " << this << G4endl;
503}
504
505//_____________________________________________________________________________
507{
509
510 // Do only once
511 if (fIsMCStackCached) return;
512
513 // The VMC stack must be set to MC at this stage !!
514 TVirtualMCStack* mcStack = gMC->GetStack();
515 if (!mcStack) {
517 "TG4RunManager", "CacheMCStack", "VMC stack is not set");
518 return;
519 }
520
521 TMCManagerStack* mcManagerStack = gMC->GetManagerStack();
522 // Set stack to the event actions if they exists
523 // (on worker only if in MT mode)
524 if (GetEventAction()) {
525 GetEventAction()->SetMCStack(mcStack);
529
532 }
533 }
534
535 fIsMCStackCached = true;
536}
537
538//_____________________________________________________________________________
545
546//_____________________________________________________________________________
547void TG4RunManager::ProcessEvent(G4int eventId, G4bool isInterruptible)
548{
550
551 // First, replay what is done in G4RunManager::BeamOn(...) explicitly
553 G4bool cond = fRunManager->ConfirmBeamOnCondition();
554 if (!cond) {
555 TG4Globals::Warning("TG4RunManager", "ProcessEvent",
556 "Bad beam condition in G4RunManager. No event processed.");
557 return;
558 }
559 fRunManager->ConstructScoringWorlds();
560 fRunManager->RunInitialization();
562 }
563 GetEventAction()->SetIsInterruptibleEvent(isInterruptible);
564
565 // Explicitly call the following 2 methods which are otherwise called from
566 // G4RunManager::BeamOn(...)
567 fRunManager->ProcessOneEvent(eventId);
568 fRunManager->TerminateOneEvent();
569}
570
571//_____________________________________________________________________________
572Bool_t TG4RunManager::ProcessRun(G4int nofEvents)
573{
575
576 // Runinit for per-event processing ==> Don't allow for process run.
578 TG4Globals::Warning("TG4RunManager", "ProcessRun",
579 "Current run is terminated first, then the requested run is processed");
580 FinishRun();
581 }
582 fInProcessRun = true;
583 fRunManager->BeamOn(nofEvents);
584 fInProcessRun = false;
585 fNEventsProcessed = nofEvents;
586 return FinishRun();
587}
588
589//_____________________________________________________________________________
591{
593 if (fInProcessRun) {
594 TG4Globals::Warning("TG4RunManager", "FinishRun",
595 "You are processing a run. To stop it, call StopRun()");
596 return false;
597 }
598 else {
600 }
601 }
602 else {
603 fRunManager->RunTermination();
606 }
607 // Pring field statistics
609
610 G4bool result = !TG4SDServices::Instance()->GetIsStopRun();
612
613 if (fRunConfiguration->IsUseOfG4Scoring()) {
614 // Dump all scoring meshes in file
615 auto g4ScoringManager = G4ScoringManager::GetScoringManager();
616 for (std::size_t i = 0; i < g4ScoringManager->GetNumberOfMesh(); ++i) {
617 auto meshName = g4ScoringManager->GetMesh(i)->GetWorldName();
618 auto fileName = meshName + ".txt";
619 g4ScoringManager->DumpAllQuantitiesToFile(meshName, fileName);
620 }
621 }
622
623 return result;
624}
625
626//_____________________________________________________________________________
628{
630
631 if (fGeantUISession) return;
632
633 // create session if it does not exist
634 fGeantUISession = new G4UIExecutive(fARGC, fARGV);
635}
636
637//_____________________________________________________________________________
639{
641
643
644 if (fGeantUISession) {
645 // interactive session
646 G4cout << "Welcome (back) in Geant4" << G4endl;
647 fGeantUISession->GetSession()->SessionStart();
648 G4cout << "Welcome (back) in Root" << G4endl;
649 }
650 else {
651 G4cout << "Geant4 UI not available." << G4endl;
652 }
653}
654
655//_____________________________________________________________________________
657{
659
661 if (fRootUISession) {
662 G4cout << "Welcome (back) in Root" << G4endl;
663 fRootUISession->Run(kTRUE);
664 G4cout << "Welcome (back) in Geant4" << G4endl;
665 }
666}
667
668//_____________________________________________________________________________
669void TG4RunManager::ProcessGeantMacro(G4String macroName)
670{
672
673 G4String command = "/control/execute " + macroName;
674 ProcessGeantCommand(command);
675}
676
677//_____________________________________________________________________________
678void TG4RunManager::ProcessRootMacro(G4String macroName)
679{
681
682 // load macro file
683 G4String macroFile = macroName;
684 macroFile.append(".C");
685 gROOT->LoadMacro(macroFile);
686
687 // execute macro function
688 G4String macroFunction = macroName;
689 macroFunction.append("()");
690 gInterpreter->ProcessLine(macroFunction);
691}
692
693//_____________________________________________________________________________
695{
697
698 G4UImanager* pUI = G4UImanager::GetUIpointer();
699 G4int result = pUI->ApplyCommand(command);
700
701 // From G4UIbatch::ExecCommand():
702 switch (result) {
703 case fCommandSucceeded:
704 break;
705 case fCommandNotFound:
706 G4cerr << "***** COMMAND NOT FOUND <" << command << "> *****" << G4endl;
707 break;
708 case fIllegalApplicationState:
709 G4cerr << "***** Illegal application state <" << command << "> *****"
710 << G4endl;
711 break;
712 default:
713 G4int pn = result % 100;
714 G4cerr << "***** Illegal parameter (" << pn << ") <" << command
715 << "> *****" << G4endl;
716 }
717}
718
719//_____________________________________________________________________________
721{
723
724 gInterpreter->ProcessLine(command);
725}
726
727//_____________________________________________________________________________
735
736//_____________________________________________________________________________
738{
740
741 G4int eventID = fRunManager->GetCurrentEvent()->GetEventID();
742 return eventID;
743}
744
745//_____________________________________________________________________________
747{
750
751 return false;
752}
Definition of the TG4ActionInitialization class.
Definition of the TG4DetConstruction class.
Definition of the TG4EventAction class.
Definition of the TG4G3PhysicsManager class.
Definition of the TG4GeometryManager class.
Definition of the TG4GeometryServices class.
Definition of the TG4Globals class and basic container types.
Definition of the TG4PhysicsManager class.
Definition of the TG4PostDetConstruction class.
Definition of the TG4RegionsManager2 class.
Definition of the TG4RegionsManager class.
Definition of the TG4RunConfiguration class.
Definition of the TG4RunManager.h class.
Definition of the TG4SDConstruction class.
Definition of the TG4SDManager class.
Definition of the TG4SDServices class.
Definition of the TG4SpecialPhysicsList class.
Definition of the TG4StackPopper class.
Definition of the TG4StateManager class.
Definition of the TG4StepManager class.
Definition of the TG4SteppingAction class.
Definition of the TG4TrackManager class.
Definition of the TG4TrackingAction class.
Definition of the TG4WorkerInitialization class.
Action Initialization class (required for MT mode)
Actions at the beginning and the end of event.
static TG4G3PhysicsManager * Instance()
void SetUserPostDetConstruction(TG4VUserPostDetConstruction *userPostDetConstruction)
void SetUserRegionConstruction(TG4VUserRegionConstruction *userRegionConstruction)
static TG4GeometryManager * Instance()
void SetUserLimits(const TG4G3CutVector &cuts, const TG4G3ControlVector &controls) const
void PrintStatistics(G4bool open, G4bool close) const
static TG4GeometryServices * Instance()
static void Warning(const TString &className, const TString &methodName, const TString &text)
static void Exception(const TString &className, const TString &methodName, const TString &text)
static TG4PhysicsManager * Instance()
Manager class for setting VMC cuts in energy in G4 regions.
Manager class for converting VMC cuts in energy in G4 regions.
Takes care of creating Geant4 user action classes using VMC.
Bool_t IsUseOfG4Scoring() const
Geant4 implementation of the TVirtualMC interface methods for access to Geant4 at run level.
void ProcessGeantCommand(G4String command)
void ConfigureRunManager()
G4bool fIsMCStackCached
the flag to cache MC stack only once
G4bool fHasEventByEventInitialization
Flag event-by-event processing.
G4int fNEventsProcessed
Number of events processed in event-by-event mode.
void SetRandomSeed()
picks up random seed from ROOT gRandom and propagates to Geant4
char ** fARGV
argv
Bool_t SecondariesAreOrdered() const
TG4VRegionsManager * fRegionsManager
regions manager
static TG4RunManager * fgMasterInstance
master instance
TApplication * fRootUISession
Root UI.
Int_t CurrentEvent() const
void ProcessRootCommand(G4String command)
static G4ThreadLocal TG4RunManager * fgInstance
thread local instance
G4bool fRootUIOwner
ownership of Root UI
G4RunManager * fRunManager
G4RunManager.
TG4RunManager()
Not implemented.
G4UIExecutive * fGeantUISession
G4 UI.
G4bool fUseRootRandom
the option to use Root random number seed
G4int fARGC
argc
void CloneRootNavigatorForWorker()
TG4RunConfiguration * fRunConfiguration
TG4RunConfiguration.
void ProcessRootMacro(G4String macroName)
void ProcessGeantMacro(G4String macroName)
Bool_t ProcessRun(G4int nofEvents)
TG4RunMessenger fMessenger
messenger
void FilterARGV(const G4String &option)
G4bool fInProcessRun
flag while being in BeamOn
virtual ~TG4RunManager()
void SetIsStopRun(G4bool stopRun)
void PrintStatistics(G4bool open, G4bool close) const
G4bool GetIsStopRun() const
static TG4SDServices * Instance()
void SetUserFastSimulation(TG4VUserFastSimulation *fastSimulation)
static TG4SpecialPhysicsList * Instance()
static TG4StackPopper * Instance()
void SetMCStack(TVirtualMCStack *mcStack)
void SetNewState(TG4ApplicationState state)
static TG4StateManager * Instance()
static TG4StepManager * Instance()
static TG4SteppingAction * Instance()
void SetMCStack(TVirtualMCStack *mcStack)
static TG4TrackManager * Instance()
void SetMCManagerStack(TMCManagerStack *mcManagerStack)
void SetMCStack(TVirtualMCStack *mcStack)
static TG4TrackingAction * Instance()
The abstract base class which is used to build fast simulation models.
virtual G4int VerboseLevel() const
Definition TG4Verbose.h:78
TG4Verbose(const G4String &cmdName)
Actions at start and end of run on a worker (call in MT mode only)
@ kMisalignGeometry
in MisalignGeometry
@ kConstructGeometry
in ConstructGeometry
@ kNotInApplication
not in VMC application