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
|
# -*- coding: utf-8 -*-
#-------------------------------------------------------------------------------
# This file is part of Code_Saturne, a general-purpose CFD tool.
#
# Copyright (C) 1998-2021 EDF S.A.
#
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
# Street, Fifth Floor, Boston, MA 02110-1301, USA.
#-------------------------------------------------------------------------------
"""
This module contains the creation of the dependancy graph between CASES.
This module contains the following classes:
- node_case
- dependency_graph
"""
#-------------------------------------------------------------------------------
# Standard modules import
#-------------------------------------------------------------------------------
import os, sys
import logging
#-------------------------------------------------------------------------------
# Application modules import
#-------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
# log config
#-------------------------------------------------------------------------------
logging.basicConfig()
log = logging.getLogger(__file__)
#log.setLevel(logging.DEBUG)
log.setLevel(logging.NOTSET)
#-------------------------------------------------------------------------------
# class node_case
#-------------------------------------------------------------------------------
class node_case:
def __init__(self, name, n_procs, n_iter, estim_wtime, tags, depends):
""" initializes a Code_Saturne CASE
"""
# name should be in the folling form: STUDY/CASE/run_id
# ex: "81_HEAD_LOSSES_COMPONENT/CASE_BEND/mesh12"
self.name = name
self.n_procs = n_procs
self.tags = tags
# TODO: verify that these parameters are well handled by smgr in general
self.n_iter = n_iter
# estimated wall time for the submission of the case on cluster
self.estim_wtime = estim_wtime
# depends should be in the same format as name
self.depends = depends
# level is modified in add_node
self.level = None
def __str__(self):
res = '\nCase ' + self.name
res += ' on ' + str(self.n_procs) + ' procs'
res += ' on ' + str(self.n_iter) + ' iterations'
res += ' with an estimated wall time of ' + str(self.estim_wtime)
res += ' with tags ' + str(self.tags)
res += ' with level ' + str(self.level)
return res
#-------------------------------------------------------------------------------
# class dependency_graph
#-------------------------------------------------------------------------------
class dependency_graph(object):
def __init__(self):
""" Initializes a dependency graph object to an empty dictionary
"""
self.graph_dict = {}
self.add_node(node_case('root', n_procs=0, n_iter=0, estim_wtime=0,
tags=None, depends=None))
def add_dependency(self, dependency):
""" Defines dependency between two node_cases as an edge in the graph
"""
(node1, node2) = dependency
if node1 in self.graph_dict:
self.graph_dict[node1].append(node2)
else:
self.graph_dict[node1] = [node2]
def add_node(self, node):
""" Add a node_case in the graph if not already there.
Add a dependency when depends parameters is defined
"""
if node not in self.graph_dict:
self.graph_dict[node] = []
root_node = self.root_node()
if node is not root_node:
if node.depends:
for neighbor in self.graph_dict:
if neighbor.name == node.depends:
# cases with dependency are level > 1 and connected to the dependency
self.add_dependency((node, neighbor))
node.level = neighbor.level + 1
break
if node.level is None:
msg = "Problem in graph construction : dependency " \
+ node.depends + " is not found.\n"
sys.exit(msg)
else:
# cases with no dependency are level 1 and connected to the root node
self.add_dependency((node, root_node))
node.level = 1
else:
# root node is level 0 and have no dependency
node.level = 0
def nodes(self):
""" returns the cases of the dependency graph """
return list(self.graph_dict.keys())
def dependencies(self):
""" returns the dependencies between the cases of the graph """
dependencies = []
for node in self.graph_dict:
for neighbor in self.graph_dict[node]:
if (neighbor, node) not in dependencies:
dependencies.append((node, neighbor))
return dependencies
def extract_sub_graph(self, level, n_procs):
""" extracts a sub_graph based on level and n_procs criteria"""
sub_graph = dependency_graph()
for node in self.graph_dict:
if node.level == level and int(node.n_procs) == n_procs:
sub_graph.add_node(node)
return sub_graph
def root_node(self):
""" returns the root node of the graph """
for node in self.graph_dict:
if node.name == 'root':
return node
def __str__(self):
res = "\nList of cases: "
for node in self.nodes():
res += str(node) + " "
res += "\nList of dependencies: "
for dependency in self.dependencies():
(node1, node2) = dependency
res += '\n' + str(node1.name) + ' depends on ' + str(node2.name)
return res
#-------------------------------------------------------------------------------
|