1#!/usr/local/bin/python3.8
2
3#-------------------------------------------------------------------------------
4
5# This file is part of Code_Saturne, a general-purpose CFD tool.
6#
7# Copyright (C) 1998-2021 EDF S.A.
8#
9# This program is free software; you can redistribute it and/or modify it under
10# the terms of the GNU General Public License as published by the Free Software
11# Foundation; either version 2 of the License, or (at your option) any later
12# version.
13#
14# This program is distributed in the hope that it will be useful, but WITHOUT
15# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16# FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
17# details.
18#
19# You should have received a copy of the GNU General Public License along with
20# this program; if not, write to the Free Software Foundation, Inc., 51 Franklin
21# Street, Fifth Floor, Boston, MA 02110-1301, USA.
22
23#-------------------------------------------------------------------------------
24
25"""
26This module describes the script used to run a study/case for Code_Saturne.
27
28This module defines the following functions:
29- process_cmd_line
30- main
31"""
32
33#===============================================================================
34# Import required Python modules
35#===============================================================================
36
37import os, sys
38import types, string, re, fnmatch
39
40import socket
41
42from optparse import OptionParser
43
44#===============================================================================
45# Classes
46#===============================================================================
47
48class controller:
49    """
50    Controller class for running computation.
51    """
52
53    #---------------------------------------------------------------------------
54
55    def __init__(self,
56                 path = None,      # run directory
57                 package = None):  # main package
58
59        # Package specific information
60
61        self.package = package
62
63        # run directory
64
65        self.path = path
66
67        # Initialize connection
68
69        import random
70
71        key = str(random.randrange(0, 2**31))
72        hostname = socket.getfqdn()
73
74        self.s = socket.socket()
75        self.s.bind(('', 0)) # OS will pick an available port.
76
77        port = self.s.getsockname()[1]
78
79        f_path = 'control_file'
80        if self.path != None:
81            f_path = os.path.append(self.path, f_path)
82        c = open(f_path, 'w')
83        c.write('connect ' + hostname+':'+str(port) + ' ' + key + '\n')
84        c.close()
85
86        self.s.listen(0)
87        (self.conn, self.address) = self.s.accept()
88
89        cmp_key = self.conn.recv(len(key)).decode("utf-8")
90        if cmp_key != key:
91            print('incorrect key returned: expected ' + key + ', got ' + cmp_key)
92
93        magic_string = 'CFD_control_comm_socket'
94        cmp_string = self.conn.recv(len(magic_string)).decode("utf-8")
95
96        if cmp_string != magic_string:
97            print('incorrect magic string returned: expected ' + magic_string)
98            print('got ' + cmp_string)
99
100        self.conn.send(magic_string.encode("utf-8"))
101
102    #---------------------------------------------------------------------------
103
104    def send_string(self, str):
105
106        self.conn.send((str + "\n").encode("utf-8"))
107        # print("sent ", str)
108
109    #---------------------------------------------------------------------------
110
111    def recv_string(self, l=32768):
112
113        str = self.conn.recv(l).decode("utf-8")
114        lr = len(str)
115        while lr >= l:
116            str0 = self.conn.recv(l).decode("utf-8")
117            l = len(str0)
118            str += str0
119        return str
120
121    #---------------------------------------------------------------------------
122
123    def advance(self, n = 1):
124
125        self.send_string("advance " + str(n))
126        retcode = self.recv_string()
127        # print(retcode)
128
129    #---------------------------------------------------------------------------
130
131    def disconnect(self):
132
133        self.send_string("disconnect ")
134
135        self.conn.shutdown(socket.SHUT_RDWR)
136        self.conn.close()
137
138        self.s.shutdown(socket.SHUT_RDWR)
139        self.s.close()
140
141    #---------------------------------------------------------------------------
142
143    def __del__(self):
144
145        self.disconnect()
146
147#-------------------------------------------------------------------------------
148# Process the command line arguments
149#-------------------------------------------------------------------------------
150
151def process_cmd_line(argv, pkg):
152    """
153    Process the passed command line arguments.
154    """
155
156    if sys.argv[0][-3:] == '.py':
157        usage = "usage: %prog [options]"
158    else:
159        usage = "usage: %prog run [options]"
160
161    parser = OptionParser(usage=usage)
162
163    parser.add_option("--exec-dir", dest="exec_dir", type="string",
164                      metavar="<case>",
165                      help="server's exection directory")
166
167    parser.set_defaults(exec_dir=None)
168
169    # Note: we could use args to pass a calculation status file as an argument,
170    # which would allow pursuing the later calculation stages.
171
172    (options, args) = parser.parse_args(argv)
173
174    return  (options.exec_dir)
175
176#===============================================================================
177# Main function
178#===============================================================================
179
180def main(argv, pkg):
181    """
182    Main function.
183    """
184
185    (exec_dir) = process_cmd_line(argv, pkg)
186
187    c = controller(exec_dir, pkg)
188
189    c.advance(3)
190    c.advance(3)
191
192    return 0
193
194#-------------------------------------------------------------------------------
195
196if __name__ == '__main__':
197
198    # Run package
199
200    try:
201        from code_saturne.cs_package import package
202        pkg = package()
203    except Exception:
204        pkg = None
205
206    retval = main(sys.argv[1:], pkg)
207
208    sys.exit(retval)
209
210#-------------------------------------------------------------------------------
211# End
212#-------------------------------------------------------------------------------
213
214