-
Notifications
You must be signed in to change notification settings - Fork 23
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
QChem Adapter & Molpro Updates #712
base: main
Are you sure you want to change the base?
Changes from all commits
62433b1
21d0e0e
8054f43
690a831
2b59d29
d38e259
c10e4f3
60dd90b
1011847
9766ad9
189eb62
2a1738c
6ca490e
ff7583c
0c23475
752f417
4852981
497628d
e304459
6143254
2b9cd67
d68720f
abb4d7f
9e49d7f
a4a3189
fd6bee1
dc366c6
2f581fd
bc3dc82
f29012c
5e4b433
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -36,6 +36,7 @@ scratch/ | |
|
||
# csv database | ||
*.csv | ||
!basis_sets.csv | ||
|
||
# iPython files | ||
*.ipynb_* | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -217,6 +217,7 @@ | |
project='test', | ||
project_directory=os.path.join(ARC_PATH, 'arc', 'testing', 'test_JobAdapter_ServerTimeLimit'), | ||
species=[ARCSpecies(label='spc1', xyz=['O 0 0 1'])], | ||
server='server1', | ||
testing=True, | ||
queue='short_queue', | ||
attempted_queues=['short_queue'] | ||
|
@@ -354,7 +355,7 @@ | |
self.job_4.cpu_cores = None | ||
self.job_4.set_cpu_and_mem() | ||
self.assertEqual(self.job_4.cpu_cores, 8) | ||
expected_memory = math.ceil((14 * 1024 * 1.1) / self.job_4.cpu_cores) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The commit message here should be something like "Minor: Style modification in job adapter test" |
||
expected_memory = math.ceil((14 * 1024 * 1.1)/self.job_4.cpu_cores) | ||
self.assertEqual(self.job_4.submit_script_memory, expected_memory) | ||
self.job_4.server = 'local' | ||
|
||
|
@@ -431,6 +432,13 @@ | |
'remote': os.path.join(self.job_1.remote_path, 'm.x'), | ||
'source': 'input_files', | ||
'make_x': True}) | ||
|
||
def test_determine_job_status(self): | ||
Check warning Code scanning / CodeQL Variable defined multiple times Warning
This assignment to 'test_determine_job_status' is unnecessary as it is
redefined Error loading related location Loading |
||
"""Test determining the job status""" | ||
self.job_5.determine_job_status() | ||
self.assertEqual(self.job_5.job_status[0], 'done') | ||
self.assertEqual(self.job_5.job_status[1]['status'], 'errored') | ||
self.assertEqual(self.job_5.job_status[1]['keywords'], ['ServerTimeLimit']) | ||
|
||
def test_determine_job_status(self): | ||
"""Test determining the job status""" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -156,6 +156,7 @@ def __init__(self, | |
self.execution_type = execution_type or 'queue' | ||
self.command = 'molpro' | ||
self.url = 'https://www.molpro.net/' | ||
self.core_change = None | ||
|
||
if species is None: | ||
raise ValueError('Cannot execute Molpro without an ARCSpecies object.') | ||
|
@@ -324,19 +325,50 @@ def set_additional_file_paths(self) -> None: | |
def set_input_file_memory(self) -> None: | ||
""" | ||
Set the input_file_memory attribute. | ||
|
||
Molpro's memory is per cpu core and in MW (mega word; 1000 MW = 7.45 GB on a 64-bit machine) | ||
The conversion from mW to GB was done using this (https://deviceanalytics.com/words-to-bytes-converter/) | ||
specifying a 64-bit architecture. | ||
See also: | ||
https://www.molpro.net/pipermail/molpro-user/2010-April/003723.html | ||
In the link, they describe the conversion of 100,000,000 Words (100Mword) is equivalent to | ||
800,000,000 bytes (800 mb). | ||
Formula - (100,000,000 [Words]/( 800,000,000 [Bytes] / (job mem in gb * 1000,000,000 [Bytes])))/ 1000,000 [Words -> MegaWords] | ||
The division by 1E6 is for converting into MWords | ||
""" | ||
# Molpro's memory is per cpu core and in MW (mega word; 1000 MW = 7.45 GB on a 64-bit machine) | ||
# The conversion from mW to GB was done using this (https://deviceanalytics.com/words-to-bytes-converter/) | ||
# specifying a 64-bit architecture. | ||
# | ||
# See also: | ||
# https://www.molpro.net/pipermail/molpro-user/2010-April/003723.html | ||
# In the link, they describe the conversion of 100,000,000 Words (100Mword) is equivalent to | ||
# 800,000,000 bytes (800 mb). | ||
# Formula - (100,000,000 [Words]/( 800,000,000 [Bytes] / (job mem in gb * 1000,000,000 [Bytes])))/ 1000,000 [Words -> MegaWords] | ||
# The division by 1E6 is for converting into MWords | ||
# Due to Zeus's configuration, there is only 1 nproc so the memory should not be divided by cpu_cores. | ||
self.input_file_memory = math.ceil(self.job_memory_gb / (7.45e-3 * self.cpu_cores)) if 'zeus' not in socket.gethostname() else math.ceil(self.job_memory_gb / (7.45e-3)) | ||
|
||
self.input_file_memory = math.ceil(self.job_memory_gb / (7.45e-3 * self.cpu_cores)) | ||
# We need to check if ess_trsh_methods=['cpu'] and ess_trsh_methods=['molpro_memory:] exists | ||
# If it does, we need to reduce the cpu_cores | ||
if self.ess_trsh_methods is not None: | ||
if 'cpu' in self.ess_trsh_methods and any('molpro_memory:' in method for method in self.ess_trsh_methods): | ||
current_cpu_cores = self.cpu_cores | ||
max_memory = self.job_memory_gb | ||
memory_values = [] | ||
for item in self.ess_trsh_methods: | ||
if 'molpro_memory:' in item: | ||
memory_value = item.split('molpro_memory:')[1] | ||
memory_values.append(float(memory_value)) | ||
|
||
if memory_values: | ||
min_memory_value = min(memory_values) | ||
available_cores = math.floor(max_memory / (min_memory_value * 7.45e-3)) | ||
if self.core_change is None: | ||
self.core_change = available_cores | ||
elif self.core_change == available_cores: | ||
# We have already done this | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I am not 100% certain, but as long as the adapter class is not re-instantiated |
||
# Reduce the cores by 1 | ||
available_cores -= 1 | ||
if available_cores < current_cpu_cores: | ||
self.cpu_cores = available_cores | ||
logger.info(f'Changing the number of cpu_cores from {current_cpu_cores} to {self.cpu_cores}') | ||
# Situation may occur when the required memory per process by Molpro is only enough for 1 cpu core for us to use (for example, 4300 MW -> 32.04GB and if we have 64GB, we can only use 1 cpu core) | ||
# And this means that for 1 CPU, we may end up using all 64GB of memory which approximates to 8600 MW. We need to take precaution here and not use all the memory. | ||
# We will therefore, limit the MW to 4300 MW | ||
self.input_file_memory = math.ceil(self.job_memory_gb / (7.45e-3 * self.cpu_cores)) | ||
if self.cpu_cores == 1 and self.input_file_memory > min_memory_value: | ||
self.input_file_memory = min_memory_value | ||
logger.info(f'Changing the input_file_memory from {self.input_file_memory} to {min_memory_value} as the number of cpu_cores will be restricted to 1 due to the memory requirements of Molpro') | ||
|
||
def execute_incore(self): | ||
""" | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -43,6 +43,37 @@ def setUpClass(cls): | |
species=[ARCSpecies(label='spc1', xyz=['O 0 0 1'])], | ||
testing=True, | ||
) | ||
cls.job_3 = MolproAdapter(execution_type='queue', | ||
job_type='opt', | ||
level=Level(method='CCSD(T)', basis='cc-pVQZ'), | ||
project='test', | ||
project_directory=os.path.join(ARC_PATH, 'arc', 'testing', 'test_MolproAdapter_2'), | ||
species=[ARCSpecies(label='spc1', xyz=['O 0 0 1'])], | ||
testing=True, | ||
ess_trsh_methods=['memory','cpu', 'molpro_memory: 2800 '], | ||
job_memory_gb=64, | ||
) | ||
cls.job_4 = MolproAdapter(execution_type='queue', | ||
job_type='opt', | ||
level=Level(method='CCSD(T)', basis='cc-pVQZ'), | ||
project='test', | ||
project_directory=os.path.join(ARC_PATH, 'arc', 'testing', 'test_MolproAdapter_2'), | ||
species=[ARCSpecies(label='spc1', xyz=['O 0 0 1'])], | ||
testing=True, | ||
ess_trsh_methods=['memory','cpu', 'molpro_memory: 4300 '], | ||
job_memory_gb=64, | ||
) | ||
|
||
cls.job_5 = MolproAdapter(execution_type='queue', | ||
job_type='opt', | ||
level=Level(method='CCSD(T)', basis='cc-pVQZ'), | ||
project='test', | ||
project_directory=os.path.join(ARC_PATH, 'arc', 'testing', 'test_MolproAdapter_2'), | ||
species=[ARCSpecies(label='spc1', xyz=['O 0 0 1'])], | ||
testing=True, | ||
ess_trsh_methods=['memory','cpu', 'molpro_memory: 2800 '], | ||
job_memory_gb=64, | ||
) | ||
|
||
def test_set_cpu_and_mem(self): | ||
"""Test assigning number of cpu's and memory""" | ||
|
@@ -52,6 +83,18 @@ def test_set_cpu_and_mem(self): | |
self.job_1.set_cpu_and_mem() | ||
self.assertEqual(self.job_1.cpu_cores, 48) | ||
|
||
def test_memory_change(self): | ||
"""Test changing the memory | ||
|
||
1. Test that the required memory is set correctly and that the number of CPUs changes accordingly | ||
2. Test that the required memory requires 1 CPU and will therefore not attempt to the total memory | ||
""" | ||
self.assertEqual(self.job_3.input_file_memory, 2864) | ||
self.assertEqual(self.job_3.cpu_cores, 3) | ||
|
||
self.assertEqual(self.job_4.input_file_memory, 4300) | ||
self.assertEqual(self.job_4.cpu_cores, 1) | ||
|
||
def test_set_input_file_memory(self): | ||
"""Test setting the input_file_memory argument""" | ||
self.job_1.input_file_memory = None | ||
|
@@ -128,6 +171,15 @@ def test_write_input_file(self): | |
""" | ||
self.assertEqual(content_2, job_2_expected_input_file) | ||
|
||
def test_core_reduction_logic(self): | ||
"""Test the core reduction logic""" | ||
|
||
# Job 5 again to trigger the condition of the core reduction logic | ||
# Job 5 technically would be 3 CPUs prior to the reactive setting the input file memory. | ||
self.job_5.set_input_file_memory() | ||
self.assertEqual(self.job_5.input_file_memory, 4296) | ||
self.assertEqual(self.job_5.cpu_cores, 2) | ||
|
||
def test_set_files(self): | ||
"""Test setting files""" | ||
job_1_files_to_upload = [{'file_name': 'submit.sub', | ||
|
@@ -141,7 +193,7 @@ def test_set_files(self): | |
'source': 'path', | ||
'make_x': False}, | ||
] | ||
job_1_files_to_download = [{'file_name': 'input.out', | ||
job_1_files_to_download = [{'file_name':'output.out', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should also change this line: https://github.com/ReactionMechanismGenerator/ARC/blob/main/arc/settings/settings.py#L165 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe it was changed in this PR |
||
'local': os.path.join(self.job_1.local_path, output_filenames[self.job_1.job_adapter]), | ||
'remote': os.path.join(self.job_1.remote_path, output_filenames[self.job_1.job_adapter]), | ||
'source': 'path', | ||
|
Check notice
Code scanning / CodeQL
Commented-out code Note