|
44 | 44 | from rmgpy.solver.mbSampled import MBSampledReactor |
45 | 45 | from rmgpy.solver.simple import SimpleReactor |
46 | 46 | from rmgpy.solver.surface import SurfaceReactor |
| 47 | +from rmgpy.solver.electrode import ElectrodeReactor |
47 | 48 | from rmgpy.util import as_list |
48 | 49 | from rmgpy.data.surface import MetalDatabase |
49 | 50 |
|
@@ -513,6 +514,109 @@ def surface_reactor(temperature, |
513 | 514 | rmg.reaction_systems.append(system) |
514 | 515 | system.log_initial_conditions(number=len(rmg.reaction_systems)) |
515 | 516 |
|
| 517 | +# Reaction systems |
| 518 | +def electrode_reactor(potential, |
| 519 | + temperature, |
| 520 | + initialPressure, |
| 521 | + initialGasMoleFractions, |
| 522 | + initialSurfaceCoverages, |
| 523 | + surfaceVolumeRatio, |
| 524 | + nSims=4, |
| 525 | + terminationConversion=None, |
| 526 | + terminationTime=None, |
| 527 | + terminationRateRatio=None, |
| 528 | + sensitivity=None, |
| 529 | + sensitivityThreshold=1e-3): |
| 530 | + logging.debug('Found electrodeReactor reaction system') |
| 531 | + |
| 532 | + for value in list(initialGasMoleFractions.values()): |
| 533 | + if value < 0: |
| 534 | + raise InputError('Initial mole fractions cannot be negative.') |
| 535 | + total_initial_moles = sum(initialGasMoleFractions.values()) |
| 536 | + if total_initial_moles != 1: |
| 537 | + logging.warning('Initial gas mole fractions do not sum to one; renormalizing.') |
| 538 | + logging.debug('') |
| 539 | + logging.debug('Original composition:') |
| 540 | + for spec, molfrac in initialGasMoleFractions.items(): |
| 541 | + logging.debug("{0} = {1}".format(spec, molfrac)) |
| 542 | + for spec in initialGasMoleFractions: |
| 543 | + initialGasMoleFractions[spec] /= total_initial_moles |
| 544 | + logging.info('') |
| 545 | + logging.debug('Normalized mole fractions:') |
| 546 | + for spec, molfrac in initialGasMoleFractions.items(): |
| 547 | + logging.debug("{0} = {1}".format(spec, molfrac)) |
| 548 | + |
| 549 | + if not isinstance(potential, list): |
| 550 | + potential = Quantity(potential) |
| 551 | + else: |
| 552 | + if len(potential) != 2: |
| 553 | + raise InputError('potential ranges can either be in the form of (number,units) or a list with 2 entries ' |
| 554 | + 'of the same format') |
| 555 | + potential = [Quantity(v) for v in potential] |
| 556 | + |
| 557 | + if not isinstance(temperature, list): |
| 558 | + T = Quantity(temperature) |
| 559 | + else: |
| 560 | + if len(temperature) != 2: |
| 561 | + raise InputError('Temperature ranges can either be in the form of (number,units) or a list with 2 entries ' |
| 562 | + 'of the same format') |
| 563 | + T = [Quantity(t) for t in temperature] |
| 564 | + |
| 565 | + if not isinstance(initialPressure, list): |
| 566 | + P_initial = Quantity(initialPressure) |
| 567 | + else: |
| 568 | + if len(initialPressure) != 2: |
| 569 | + raise InputError('Initial pressure ranges can either be in the form ''of (number,units) or a list with ' |
| 570 | + '2 entries of the same format') |
| 571 | + P_initial = [Quantity(p) for p in initialPressure] |
| 572 | + |
| 573 | + if not isinstance(temperature, list) and not isinstance(initialPressure, list): |
| 574 | + nSims = 1 |
| 575 | + if any([isinstance(x, list) for x in initialGasMoleFractions.values()]) or \ |
| 576 | + any([isinstance(x, list) for x in initialSurfaceCoverages.values()]): |
| 577 | + raise NotImplementedError("Can't do ranges on species concentrations for surface reactors yet.") |
| 578 | + |
| 579 | + termination = [] |
| 580 | + if terminationConversion is not None: |
| 581 | + for spec, conv in terminationConversion.items(): |
| 582 | + termination.append(TerminationConversion(species_dict[spec], conv)) |
| 583 | + if terminationTime is not None: |
| 584 | + termination.append(TerminationTime(Quantity(terminationTime))) |
| 585 | + if terminationRateRatio is not None: |
| 586 | + termination.append(TerminationRateRatio(terminationRateRatio)) |
| 587 | + if len(termination) == 0: |
| 588 | + raise InputError('No termination conditions specified for reaction system #{0}.'.format(len(rmg.reaction_systems) + 2)) |
| 589 | + |
| 590 | + sensitive_species = [] |
| 591 | + if sensitivity: |
| 592 | + for spec in sensitivity: |
| 593 | + sensitive_species.append(species_dict[spec]) |
| 594 | + if not isinstance(T, list): |
| 595 | + sensitivityTemperature = T |
| 596 | + if not isinstance(initialPressure, list): |
| 597 | + sensitivityPressure = initialPressure |
| 598 | + sens_conditions = None |
| 599 | + if sensitivity: |
| 600 | + raise NotImplementedError("Can't currently do sensitivity with surface reactors.") |
| 601 | + # The problem is inside base.pyx it reads the dictionary 'sensConditions' |
| 602 | + # and guesses whether they're all concentrations (liquid reactor) or |
| 603 | + # mole fractions (simple reactor). In fact, some may be surface coverages. |
| 604 | + |
| 605 | + system = ElectrodeReactor(potential=potential, |
| 606 | + T=T, |
| 607 | + P_initial=P_initial, |
| 608 | + initial_gas_mole_fractions=initialGasMoleFractions, |
| 609 | + initial_surface_coverages=initialSurfaceCoverages, |
| 610 | + surface_volume_ratio=surfaceVolumeRatio, |
| 611 | + surface_site_density=rmg.surface_site_density, |
| 612 | + n_sims=nSims, |
| 613 | + termination=termination, |
| 614 | + sensitive_species=sensitive_species, |
| 615 | + sensitivity_threshold=sensitivityThreshold, |
| 616 | + sens_conditions=sens_conditions) |
| 617 | + rmg.reaction_systems.append(system) |
| 618 | + system.log_initial_conditions(number=len(rmg.reaction_systems)) |
| 619 | + |
516 | 620 |
|
517 | 621 | # Reaction systems |
518 | 622 | def mb_sampled_reactor(temperature, |
@@ -959,6 +1063,7 @@ def read_input_file(path, rmg0): |
959 | 1063 | 'simpleReactor': simple_reactor, |
960 | 1064 | 'liquidReactor': liquid_reactor, |
961 | 1065 | 'surfaceReactor': surface_reactor, |
| 1066 | + 'electrodeReactor': electrode_reactor, |
962 | 1067 | 'mbsampledReactor': mb_sampled_reactor, |
963 | 1068 | 'simulator': simulator, |
964 | 1069 | 'solvation': solvation, |
|
0 commit comments