def importScene(filePath): ''' **Return the graph of a SOFA scene** Thanks to the SOFA Launcher, it will launch a templated scene that will extract from an original scene its content as 2 dictionnaries containing: - The different Sofa.node of the scene keeping there hierarchy - All the SOFA component contained in each node with the node.name as key +----------+------+---------------------------------+ | argument | type | definition | +==========+======+=================================+ | filePath | str | Absolute path to the SOFA scene | +----------+------+---------------------------------+ ''' numiterations = 1 filename = "importScene.py" path = os.path.dirname(os.path.abspath(__file__)) + '/template/' filesandtemplates = [(open(path + filename).read(), filename)] listSofaScene = [{ "ORIGINALSCENE": filePath, "nbIterations": numiterations }] results = startSofa(listSofaScene, filesandtemplates, launcher=SerialLauncher()) with open(results[0]["directory"] + '/graphScene.yml', 'r') as ymlfile: cfg = yaml.load(ymlfile) return cfg
def phase1(self, phasesToExecute=None): """ **The step will launch in parallel multiple Sofa scene (nbrCPU by nbrCPU number of scene) until it has run all the scene in the sequence.** +-----------------+-----------+----------------------------------------------------------+ | argument | type | definition | +=================+===========+==========================================================+ | phasesToExecute | list(int) || Allow to choose which phase to execute for the reduction| | | || *more details see* :py:func:`setListSofaScene` | +-----------------+-----------+----------------------------------------------------------+ To run the SOFA scene in parallele we use the ``sofa launcher`` utility What does it do to each scene: - Add animation to each :py:class:`.ObjToAnimate` we want for our model in the predifined sequence - Add a componant to save the shaking resulting states (WriteState) - Take all the resulting states files and combines them in one file put in the ``debug`` dir with a debug scene """ start_time = time.time() if not phasesToExecute: phasesToExecute = list( range(self.reductionAnimations.nbPossibility)) self.setListSofaScene(phasesToExecute) filenames = ["phase1_snapshots.py", "debug_scene.py"] filesandtemplates = [] for filename in filenames: filesandtemplates.append( (open(pathToTemplate + filename).read(), filename)) results = startSofa(self.listSofaScene, filesandtemplates, launcher=ParallelLauncher(self.nbrCPU)) if self.verbose: for res in results: print("Results: ") print(" directory: " + res["directory"]) print(" scene: " + res["scene"]) print(" duration: " + str(res["duration"]) + " sec") self.packageBuilder.copyAndCleanState( results, self.reductionParam.periodSaveGIE, self.reductionParam.stateFileName, self.reductionParam.velocityFileName) u.copy( results[self.phaseToSaveIndex]["directory"] + slash + "debug_scene.py", self.packageBuilder.debugDir) print("PHASE 1 --- %s seconds ---" % (time.time() - start_time))
def phase4(self, nbrOfModes=None): """ **The final step will gather all the results in 1 folder and build a reusable scene from it** +-----------------+-----------+----------------------------------------------------------+ | argument | type | definition | +=================+===========+==========================================================+ | nbrOfModes | int || Number of modes you want to keep | | | || ``by default will keep them all`` | +-----------------+-----------+----------------------------------------------------------+ Final step : - compute the RID and Weigts with :py:mod:`.ReadGieFileAndComputeRIDandWeights` - compute the Active Nodes with :py:mod:`.ConvertRIDinActiveNodes` - finalize the package - add it to the plugin library if option activated """ # MOR IMPORT from .script import readGieFileAndComputeRIDandWeights, convertRIDinActiveNodes start_time = time.time() if not os.path.isfile(self.packageBuilder.dataDir + self.reductionParam.modesFileName): raise IOError("There is no mode file at "+self.packageBuilder.dataDir+self.reductionParam.modesFileName\ +"\nPlease give one at this location or indicate the correct location or re-generate one with phase 1 & 2") nbrOfModesPossible = self.packageBuilder.checkNodeNbr( self.reductionParam.modesFileName) if not nbrOfModes: nbrOfModes = self.reductionParam.nbrOfModes if nbrOfModes == -1: nbrOfModes = self.reductionParam.nbrOfModes = nbrOfModesPossible if (nbrOfModes <= 0) or (nbrOfModes > nbrOfModesPossible): raise ValueError("nbrOfModes incorrect\n"\ +" nbrOfModes given :"+str(nbrOfModes)+" | nbrOfModes max possible : "+str(nbrOfModesPossible)) # print(files) files = glob.glob(self.packageBuilder.debugDir + "*_elmts.txt") if files: for i, file in enumerate(files): file = os.path.normpath(file) files[i] = file.split(slash)[-1] # print("FILES ----------->",files) self.reductionParam.savedElementsFilesNames = files files = glob.glob(self.packageBuilder.debugDir + "*_Gie.txt") if files: for i, file in enumerate(files): file = os.path.normpath(file) files[i] = file.split(slash)[-1] # print("FILES ----------->",files) self.reductionParam.gieFilesNames = files for i, gie in enumerate(self.reductionParam.gieFilesNames): tmp = gie.replace('_Gie.txt', '') for j, elmts in enumerate( self.reductionParam.savedElementsFilesNames): if tmp in elmts: tmp = self.reductionParam.savedElementsFilesNames[j] self.reductionParam.savedElementsFilesNames[ j] = self.reductionParam.savedElementsFilesNames[i] self.reductionParam.savedElementsFilesNames[i] = tmp # print(self.reductionParam.savedElementsFilesNames) # print(self.reductionParam.gieFilesNames) tmp = glob.glob(self.packageBuilder.dataDir + "*_reduced.txt")[0] tmp = os.path.normpath(tmp) self.reductionParam.massName = tmp.split(slash)[-1] # print("massName -----------------------> ",self.reductionParam.massName) self.reductionParam.RIDFilesNames = [] self.reductionParam.weightsFilesNames = [] self.reductionParam.listActiveNodesFilesNames = [] for fileName in self.reductionParam.gieFilesNames: if not os.path.isfile(self.packageBuilder.debugDir + fileName): raise IOError("There is no GIE file at "+self.packageBuilder.debugDir+fileName\ +"\nPlease give one at this location or indicate the correct location or re-generate one with phase 3") self.reductionParam.RIDFilesNames.append( fileName.replace('_Gie', '_RID')) self.reductionParam.weightsFilesNames.append( fileName.replace('_Gie', '_weight')) self.reductionParam.listActiveNodesFilesNames.append( fileName.replace('_Gie', '_listActiveNodes')) self.listActiveNodesFilesNames = [] for i, fileName in enumerate(self.reductionParam.gieFilesNames): # index = self.reductionParam.gieFilesNames.index(fileName) readGieFileAndComputeRIDandWeights( self.packageBuilder.debugDir + fileName, self.packageBuilder.dataDir + self.reductionParam.RIDFilesNames[i], self.packageBuilder.dataDir + self.reductionParam.weightsFilesNames[i], self.reductionParam.tolGIE, verbose=self.verbose) # print(index) # print(len(self.reductionParam.savedElementsFilesNames)) # if index-1 < len(self.reductionParam.savedElementsFilesNames): self.activesNodesLists.append( convertRIDinActiveNodes( self.packageBuilder.dataDir + self.reductionParam.RIDFilesNames[i], self.packageBuilder.debugDir + self.reductionParam.savedElementsFilesNames[i], self.packageBuilder.dataDir + self.reductionParam.listActiveNodesFilesNames[i], verbose=self.verbose)) finalListActiveNodes = [] for activeNodes in self.activesNodesLists: finalListActiveNodes = list(set().union(finalListActiveNodes, activeNodes)) finalListActiveNodes = sorted(finalListActiveNodes) with open(self.packageBuilder.dataDir + 'listActiveNodes.txt', "w") as file: for item in finalListActiveNodes: file.write("%i\n" % item) file.close() filename = "phase3_performECSW.py" filesandtemplates = [(open(pathToTemplate + filename).read(), filename) ] self.reductionParam.addParamWrapper(self.nodeToReduce, prepareECSW=False) finalScene = {} finalScene["ORIGINALSCENE"] = self.originalScene finalScene["PARAMWRAPPER"] = self.reductionParam.paramWrapper finalScene['NBROFMODES'] = nbrOfModes finalScene["nbIterations"] = 1 finalScene["ANIMATIONPATHS"] = self.reductionAnimations.listOfLocation finalScene["PACKAGENAME"] = self.packageBuilder.packageName results = startSofa([finalScene], filesandtemplates, launcher=ParallelLauncher(1)) self.packageBuilder.finalizePackage(results[0])
def phase3(self, phasesToExecute=None, nbrOfModes=None): """ **This step will launch in parallel multiple Sofa scene (nbrCPU by nbrCPU number of scene) until it has run all the scene in the sequence.** +-----------------+-----------+----------------------------------------------------------+ | argument | type | definition | +=================+===========+==========================================================+ | phasesToExecute | list(int) || Allow to choose which phase to execute for the reduction| | | || *more details see* :py:func:`setListSofaScene` | +-----------------+-----------+----------------------------------------------------------+ | nbrOfModes | int || Number of modes you want to keep | | | || ``by default will keep them all`` | +-----------------+-----------+----------------------------------------------------------+ To run the SOFA scene in parallele we use the ``sofa launcher`` utility What does it do to each scene: - Take the previous one and add the model order reduction component: - HyperReducedFEMForceField - MappedMatrixForceFieldAndMas - ModelOrderReductionMapping - Produce an Hyper Reduced description of the model - Produce files listing the different element to keep - Take all the resulting states files and combines them in one file put in the ``debug`` dir with a debug scene """ start_time = time.time() if not phasesToExecute: phasesToExecute = list( range(self.reductionAnimations.nbPossibility)) if not nbrOfModes: nbrOfModes = self.reductionParam.nbrOfModes if not os.path.isfile(self.packageBuilder.dataDir + self.reductionParam.modesFileName): raise IOError("There is no mode file at "+self.packageBuilder.dataDir+self.reductionParam.modesFileName\ +"\nPlease give one at this location or indicate the correct location or re-generate one with phase 1 & 2") nbrOfModesPossible = self.packageBuilder.checkNodeNbr( self.reductionParam.modesFileName) if not nbrOfModes: nbrOfModes = self.reductionParam.nbrOfModes if nbrOfModes == -1: nbrOfModes = self.reductionParam.nbrOfModes = nbrOfModesPossible if (nbrOfModes <= 0) or (nbrOfModes > nbrOfModesPossible): raise ValueError("nbrOfModes incorrect\n"\ +" nbrOfModes given :"+str(nbrOfModes)+" | nbrOfModes max possible : "+str(nbrOfModesPossible)) self.setListSofaScene(phasesToExecute) for i in range(len(phasesToExecute)): self.listSofaScene[i]['NBROFMODES'] = nbrOfModes filenames = [ "phase2_prepareECSW.py", "phase1_snapshots.py", "debug_scene.py" ] filesandtemplates = [] for filename in filenames: filesandtemplates.append( (open(pathToTemplate + filename).read(), filename)) results = startSofa(self.listSofaScene, filesandtemplates, launcher=ParallelLauncher(self.nbrCPU)) if self.verbose: for res in results: print("Results: ") print(" directory: " + res["directory"]) print(" scene: " + res["scene"]) print(" duration: " + str(res["duration"]) + " sec") files = glob.glob(results[self.phaseToSaveIndex]["directory"] + slash + "*_elmts.txt") if files: for i, file in enumerate(files): file = os.path.normpath(file) files[i] = file.split(slash)[-1] # print("FILES ----------->",files) self.reductionParam.savedElementsFilesNames = files for fileName in self.reductionParam.savedElementsFilesNames: u.copyFileIntoAnother( results[self.phaseToSaveIndex]["directory"] + slash + fileName, self.packageBuilder.debugDir + fileName) self.reductionParam.massName = glob.glob( results[self.phaseToSaveIndex]["directory"] + slash + "*_reduced.txt")[0] # print("massName -----------------------> ",self.reductionParam.massName) u.copy(self.reductionParam.massName, self.reductionParam.dataDir) files = glob.glob(results[self.phaseToSaveIndex]["directory"] + slash + "*_Gie.txt") if files: for i, file in enumerate(files): file = os.path.normpath(file) files[i] = file.split(slash)[-1] # print("FILES ----------->",files) self.reductionParam.gieFilesNames = files else: raise IOError("Missing GIE Files") self.packageBuilder.copyAndCleanState( results, self.reductionParam.periodSaveGIE, 'step2_' + self.reductionParam.stateFileName, gie=self.reductionParam.gieFilesNames) print("PHASE 3 --- %s seconds ---" % (time.time() - start_time))