crunchflow 2.0.2__tar.gz → 2.0.3__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: crunchflow
3
- Version: 2.0.2
3
+ Version: 2.0.3
4
4
  Summary: A Python toolbox for working with the CrunchFlow reactive transport code
5
5
  License: GPL-3.0-or-later
6
6
  Author: Zach Perzan
@@ -476,7 +476,7 @@ class Gases(SpeciesBlock):
476
476
  pass
477
477
 
478
478
 
479
- class KineticsBlock(KeywordBlock):
479
+ class SurfaceComplexation(KeywordBlock):
480
480
  def __init__(self):
481
481
  super().__init__()
482
482
  self.species = []
@@ -494,8 +494,43 @@ class KineticsBlock(KeywordBlock):
494
494
  return "\n".join(result)
495
495
 
496
496
 
497
- class SurfaceComplexation(KineticsBlock):
498
- pass
497
+ class KineticsBlock(KeywordBlock):
498
+ def __init__(self):
499
+ super().__init__()
500
+ self.species_dict = {}
501
+ self.species = []
502
+
503
+ def set_parameters(self, parameters):
504
+ for species, details in parameters.items():
505
+ label = details.pop('label', None)
506
+ if species not in self.species_dict:
507
+ self.species_dict[species] = {}
508
+ self.species.append(species)
509
+ if label:
510
+ self.species_dict[species][label] = details
511
+ else:
512
+ self.species_dict[species]['default'] = details
513
+
514
+ def update_parameters(self, species, label, new_details):
515
+ if species in self.species_dict and label in self.species_dict[species]:
516
+ self.species_dict[species][label].update(new_details)
517
+ else:
518
+ print(f"Species '{species}' with label '{label}' not found.")
519
+
520
+ def __str__(self):
521
+ result = []
522
+ for species, labels in self.species_dict.items():
523
+ if 'default' in labels and not labels['default']:
524
+ result.append(f"{species:<20}")
525
+ else:
526
+ for label, details in labels.items():
527
+ if label == 'default' and not details:
528
+ result.append(f"{species:<20}")
529
+ else:
530
+ details_str = ' '.join(f'-{k} {v}' for k, v in details.items())
531
+ label_str = f"-label {label} " if label != 'default' else ""
532
+ result.append(f"{species:<20} {label_str}{details_str}")
533
+ return "\n".join(result)
499
534
 
500
535
 
501
536
  class Minerals(KineticsBlock):
@@ -63,7 +63,7 @@ class InputFile:
63
63
  # Initialize other blocks as needed
64
64
 
65
65
  def set_block(self, block_name, parameters):
66
- """Set the parameters for a block in the Run instance.
66
+ """Set the parameters of a block in an InputFile instance.
67
67
 
68
68
  Parameters
69
69
  ----------
@@ -93,11 +93,9 @@ class InputFile:
93
93
  # Note that the "CONDITION <name>" is included in
94
94
  # Condition.__str__ method, so it is omitted here
95
95
  result.append(f"{str(condition)}\nEND")
96
- # elif isinstance(value, list):
97
- # for item in value:
98
- # if any(val for val in item.__dict__.values() if val):
99
- # block_name = format_class_name(item.__class__.__name__)
100
- # result.append(f"{block_name}\n{str(item)}\nEND")
96
+
97
+ # Otherwise, check if the block has any attributes set
98
+ # and if so, format the block name then print it
101
99
  elif any(val for val in value.__dict__.values() if val):
102
100
  block_name = format_class_name(value.__class__.__name__)
103
101
  result.append(f"{block_name}\n{str(value)}\nEND")
@@ -114,7 +112,12 @@ class InputFile:
114
112
  The path to the output file. Default is the current directory.
115
113
  update_pestcontrol : bool, optional
116
114
  Whether to update PestControl.ant with the name of the
117
- CrunchFlow input file. Default is False."""
115
+ CrunchFlow input file. Default is False.
116
+
117
+ Returns
118
+ -------
119
+ None
120
+ The CrunchFlow input file is saved to disk."""
118
121
 
119
122
  full_path = os.path.join(path, filename)
120
123
  with open(full_path, 'w') as file:
@@ -127,7 +130,7 @@ class InputFile:
127
130
  if update_pestcontrol:
128
131
  folder = os.path.dirname(full_path)
129
132
  pestfile = os.path.join(folder, 'PestControl.ant')
130
- with open('PestControl.ant', 'w') as file:
133
+ with open(pestfile, 'w') as file:
131
134
  file.write('%s \n' % os.path.basename(full_path))
132
135
 
133
136
  @classmethod
@@ -160,7 +163,7 @@ class InputFile:
160
163
  # Define attributes and blocks to be handled as special cases
161
164
  # SpeciesBlock and KineticsBlock instances are handled differently below
162
165
  species_blocks = ['primary_species', 'secondary_species', 'gases']
163
- kinetics_blocks = ['minerals', 'aqueous_kinetics', 'surface_complexation']
166
+ kinetics_blocks = ['minerals', 'aqueous_kinetics']
164
167
 
165
168
  # Some attributes can be set multiple times within a single block
166
169
  multiply_defined = ['time_series', 'pressure', 'mineral',
@@ -229,13 +232,35 @@ class InputFile:
229
232
  parts = line.split()
230
233
  current_block.species.append(parts[0])
231
234
 
232
- elif current_block_name in kinetics_blocks:
235
+ elif current_block_name == 'surface_complexation':
233
236
  parts = line.split()
234
237
  species = parts[0]
235
238
  details = " ".join(parts[1:]) if len(parts) > 1 else ""
236
239
  current_block.species.append(species)
237
240
  current_block.species_dict[species] = details
238
241
 
242
+ elif current_block_name in kinetics_blocks:
243
+ parts = line.split()
244
+ species = parts[0]
245
+ details = {}
246
+
247
+ # Assume the default label
248
+ # This will be updated below if it is included in details
249
+ label = 'default'
250
+
251
+ # If there are details associated with the species_dict, then parse them
252
+ if len(parts) > 1:
253
+ # Loop through kinetic options (e.g., -activation, -rate, etc.)
254
+ # and store this information in a dictionary
255
+ for i in range(1, len(parts), 2):
256
+ key = parts[i].lstrip('-')
257
+ value = parts[i+1] if (i+1) < len(parts) else None
258
+ if key == 'label':
259
+ label = value
260
+ else:
261
+ details[key] = value
262
+ current_block.set_parameters({species: {**details, 'label': label}})
263
+
239
264
  # All other blocks, split on whitespace
240
265
  else:
241
266
  parts = line.split()
@@ -197,6 +197,29 @@ class SpatialProfile:
197
197
  Get line segments that outline all the regions equal to
198
198
  the provided value.
199
199
 
200
+ __init__(fileprefix, folder, output_times, suffix)
201
+ Read in and get basic info about all .tec files matching `fileprefix`.
202
+ For example, `tec('volume')` will read in all files matching
203
+ 'volume[0-9]+.tec'
204
+
205
+ Parameters
206
+ ----------
207
+ fileprefix : str
208
+ file prefix of the tec file to read in, without the timestep
209
+ number or ".tec" file ending. For example, if your files are
210
+ "volume1.tec", "volume2.tec", etc., then fileprefix should be
211
+ "volume".
212
+ folder : str, optional
213
+ folder in which the .tec files are located. The default is the
214
+ current directory
215
+ output_times : list of float, optional
216
+ list of the actual output times at which the .tec files were
217
+ output, in CrunchFlow time units
218
+ suffix : str, optional
219
+ file ending of the tec files to read in. This can vary depending on the
220
+ version of CrunchTope used. The default is '.tec', but '.out' is also
221
+ tried if '.tec' files are not found.
222
+
200
223
  Examples
201
224
  --------
202
225
  >>> vol = SpatialProfile('volume')
@@ -207,7 +230,7 @@ class SpatialProfile:
207
230
 
208
231
  def __init__(self, fileprefix, folder='.', output_times=None, suffix='.tec'):
209
232
  """Read in and get basic info about all .tec files matching `fileprefix`.
210
- For example, `tec('volume')` will read in all files matching
233
+ For example, `SpatialProfile('volume')` will read in all files matching
211
234
  'volume[0-9]+.tec'
212
235
 
213
236
  Parameters
@@ -217,13 +240,13 @@ class SpatialProfile:
217
240
  number or ".tec" file ending. For example, if your files are
218
241
  "volume1.tec", "volume2.tec", etc., then fileprefix should be
219
242
  "volume".
220
- folder : str
243
+ folder : str, optional
221
244
  folder in which the .tec files are located. The default is the
222
245
  current directory
223
- output_times : list of float
246
+ output_times : list of float, optional
224
247
  list of the actual output times at which the .tec files were
225
248
  output, in CrunchFlow time units
226
- suffix : str
249
+ suffix : str, optional
227
250
  file ending of the tec files to read in. This can vary depending on the
228
251
  version of CrunchTope used. The default is '.tec', but '.out' is also
229
252
  tried if '.tec' files are not found.
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "crunchflow"
3
- version = "2.0.2"
3
+ version = "2.0.3"
4
4
  description = "A Python toolbox for working with the CrunchFlow reactive transport code"
5
5
  authors = ["Zach Perzan <zach.perzan@unlv.edu>"]
6
6
  license = "GPL-3.0-or-later"
File without changes
File without changes