Change Log¶
This document records notable changes to QSDsan. We aim to follow Semantic Versioning.
1.5.3¶
Raised the minimum BioSTEAM to
2.53.11and Thermosteam to0.53.5, and removedTEA’s first-equipment-replacement compensation now that BioSTEAM books it itself (otherwise it is double-counted).Fixed
TEAconstruction against newer BioSTEAM (set_startdirectly and defaultinflation_rateonly when that slot exists).qsdsan.default()now takesutilities,CEPCI, andflowsheetarguments (all defaultTrue, mirroringbiosteam.default) so users can choose what to reset;flowsheetdefaults toTrue(vs. BioSTEAM’sFalse) to preserve prior behavior.Constructing a
Componentby name/identifier now produces the same fully-initialized component asfrom_chemical(), including phase-overridden species (which previously kept an enthalpy model referenced to the wrong phase, giving a wrong reference enthalpy or asimulate()crash).search_IDnow takes only a lookup name andchemicalonly a pre-builtthermosteam.Chemical;from_chemicalis a thin wrapper. One behavior change:from_chemical(chemical='<name>', formula=<override>)now reports the override formula’s molecular weight.Added a
formula_overrideargument (defaultFalse) toComponent/from_chemical()that gates overriding a resolved chemical’s formula with a different atomic composition (a re-spelling of the same atoms or a blank custom component is not gated). EXPOsan components that legitimately override now passformula_override=True(Struvite,FilterBag,Zeolite).Added runnable docstring
Examplesto many built-in unit operations (sanitation, static, and wastewater-treatment units), backed by newqsdsan.utils.create_example_sanitation_components()andqsdsan.utils.create_example_wwt_components()helpers; all run underpytest --doctest-modules. Fixed theIncineratorexample and added BioSTEAM APISee Alsolinks to thebst-namespace units.Fixed equipment and construction lifetimes so they reach
equipment_lifetime, the attribute TEA and LCA actually read (they were previously written to_default_equipment_lifetimeand silently dropped, so replacement costs/impacts were never charged). This shifts TEA/LCA results for systems with sub-project-lifetime equipment, within existing EXPOsan tolerances.lifetimeis now the recommended name for a unit’s equipment lifetime.Fixed
TEAnet present value and replacement-cost calculations for anAgileSystem(per-unit capital objects exposeequipment_lifetime, notlifetime).Fixed
get_unit_annualized_equipment_cost(): a shadowed loop variable mis-computed the annualized cost when a unit declared per-equipment lifetimes; each item is now annualized over its own lifetime.Fixed
DynamicInfluentfor non-cyclic input data: the padding branch used the removedDataFrame.append(a silent no-op before pandas 2.0, anAttributeErrorafter); it now usespd.concat. Default cyclic input is unchanged.Added a public
dynamic_parametersaccessor onProcess/CompiledProcesses(mirrorsparameters), so users no longer reach into the private_dyn_params.load_from_file()now supports per-process conservation rules:conserved_foris keyword-only and required, accepting a uniform tuple, a per-process dict, orNoneto defer to a newconserved_fordata-file column. Backward incompatibility: callers that omittedconserved_formust now pass it explicitly.Fixed the SanUnit-mixin plumbing on eight
bst-namespace wrappers (distillation columns,Flash,IsothermalCompressor,ProcessWaterCenter,HeatExchangerNetwork) whereSanUnit.__init__never ran, so LCA/add-on attributes and kwargs (lifetime,add_OPEX, etc.) were silently dropped. The mixin-install logic was extracted into a sharedself._init_sanunit_addons(...).Harmonized the six
qsdsan.statsplotting helpers: everyplot_*now acceptsax=Noneand**plot_kwsforwarded to the underlying plotting call.plot_correlations’s**kwargswas renamed to**plot_kws(named callers unaffected), and a latentax=-dropping bug inplot_sobol_resultswas fixed.Made
qsdsana more self-contained namespace so users rarely need to import biosteam/thermosteam directly. Newly re-exported:settings,preferences,stream_utility_prices,Thermo,UtilityAgent,Facility,AgileSystem,get_OSBL,MissingStream, andreport;qsdsan.unit_operations.bstsurfaces more un-customized BioSTEAM units;qsdsan.utilsre-exportsrho_to_V,V_to_rho,@cost,var_columns/var_indices. A new BioSTEAM API page lists the full surface.qsdsan.utilsnow wraps BioSTEAM’s@costdecorator to also acceptCEPCIas an alias forCE(BioSTEAM’sCEkeyword still works).Fixed
qsdsan.utils.indices.ChemPPI_by_year: the 2021/2022 entries had been mistakenly populated with CEPCI values and have been removed, so the series ends at 2020 until authentic values are added.Fixed compatibility with newer Thermosteam (
>=0.53.4) whereChemical.MWis read-only: theMW = 1.placeholder for formula-less components now goes throughqsdsan._compat.set_chemical_MW. This unblockedComponents.load_defaultand nearly every system build.Unified report generation across
System,TEA, andLCA:save_reporton any of the three now produces the same workbook (with anLCAsheet when the system has anLCA).save_report()delegates to it and its default filename changed to{system.ID}_report.xlsx; useget_impact_table()for the LCA tables alone.Added a
time_frameargument ('lifetime'/'all'default,'yr','month','week','day','hr') to theLCAresults methods. The existingannualflag is kept as a backward-compatible alias fortime_frame='yr'.Added
get_normalized_impacts()(impacts per kg/m³/MJ of reference streams, the LCA counterpart toTEA.solve_price) andget_allocated_impact_table()(tabular counterpart ofget_allocated_impacts(), available as an opt-in report sheet).Several
LCAfixes:get_unit_impacts()no longer double-counts stream impacts;get_allocated_impacts()accepts a function forallocate_by;get_impact_table()writes theSumrow via.loc(fixing blank totals under pandas ≥ 2.x) and handles empty'Stream'/'Other'categories under pandas 3.0;add_other_item()now names the missing ID in its error.Added
qsdsan.utils.create_example_treatment_systems()(the aerobic/anaerobic wastewater systems shared by the TEA and LCA tutorials); the LCA tutorial now uses it instead of thebwaiseEXPOsan system.In EXPOsan, restored the documented
exposan.bsm1.cmps/components/asmmodule attributes (their assignment inbsm1.load()was commented out, so they stayedNoneafter a freshload()), and replaced deprecated per-testclear_lca_registries()calls with an autouseconftest.pyfixture.Substantially expanded and reorganized the tutorials and FAQ (new tutorials and sections on operational flexibility, recycle convergence, specifications, auxiliary units, cost/environmental trade-offs, and the dynamic process-modeling tutorials; a multi-page FAQ; dark-mode rendering fixes).
1.5.2¶
Fixed packaging:
qsdsan/units_of_measure.txt(the pint unit-definition file loaded at import) was not declared inpackage-data, so non-editable installs (wheels) omitted it andimport qsdsanraisedFileNotFoundError. It is now included in the distributed package.Fixed
copy_like(): when called withcopy_price=Trueorcopy_impact_item=True, the price/impact item were copied in the wrong direction (overwriting the source stream and leaving the target unchanged). They are now correctly copied from the source into the target.Added doctest examples to
copy(),copy_like(), andcopy_flow()documenting what each method copies (flows, temperature/pressure, price, and impact item).Added
.. warning::notes topHandSAlkclarifying that these are not calculated from stream composition (no acid-base model yet) and should be treated as user-provided inputs.Fixed
HXutility: its_unitsdictionary was inadvertently set toNone(it was assigned the return value ofdict.update, which is alwaysNone), which brokeresults()with anAttributeErrorand mutated BioSTEAM’s shared_units. The unit-of-measure entries are now built with a dict merge.Re-exported the Thermosteam reaction classes (
Reaction,ReactionItem,ReactionSet,ParallelReaction,SeriesReaction,ReactionSystem, and theRxn/RxnI/RxnS/PRxn/SRxn/RxnSysaliases) from the top-levelqsdsannamespace, so they can be imported withfrom qsdsan import Reactioninstead of reaching into BioSTEAM/Thermosteam.Added
qsdsan.CEPCI, a settable view of the global Chemical Engineering Plant Cost Index (which BioSTEAM abbreviates asCE), so the costing index can be read and set (e.g.,qsdsan.CEPCI = qsdsan.CEPCI_by_year[2023]) without importing biosteam.Fixed
TEA: itsCEPCIargument defaulted tobst.CE, which Python binds once at import time (freezing it at 567.5). EveryTEAcreated without an explicitCEPCItherefore reset the global cost index, silently overriding a deliberately setqsdsan.CEPCI/bst.CE.CEPCInow defaults toNone(the current index is left untouched), and a providedCEPCIis applied before simulation so it actually affects costing.CEPCI_by_yearnow returnsqsdsan.CEPCI_by_year(was BioSTEAM’s table) for consistency, andqsdsan.CEPCI_by_yearnow merges in BioSTEAM’sdesign_tools.CEPCI_by_yearyears not already present (e.g., pre-1990), with qsdsan’s more precise values taking precedence on overlapping years. QSDsan’s built-in hydroprocessing/hydrothermal units now source their@costreference indices fromqsdsan.CEPCI_by_yearas well (a sub-0.1% cost change from the more precise values).In EXPOsan, systems that set the global cost index (
htlandsaf) now do so viaqsdsan.CEPCI = ...instead ofbst.CE = ..., for consistency with the newqsdsan.CEPCIhandle (functionally identical, sinceqsdsan.CEPCIis a live view ofbst.CE).Renamed the cost-index dicts in
qsdsan.utils.indicesand the keys ofqsdsan.utils.tea_indicesto the*_by_yearconvention ('CEPCI_by_year','ChemPPI_by_year','labor_by_year','PCEPI_by_year'). Update any code that used the old short keys, e.g.,tea_indices['CEPCI']becomestea_indices['CEPCI_by_year'].Tutorial updates ongoing.
1.5.1¶
Componentnow validates theparticle_size,degradability, andorganicarguments at creation, for both the constructor andfrom_chemical(). Invalid values (e.g., a misspelledparticle_size) that were previously accepted silently now raise aValueError.The
f_BOD5_COD,f_uBOD_COD, andf_Vmass_Totmassfractions are now range-checked to[0, 1](this check was previously unreachable).The
Componentconstructor now accepts achemicalkeyword to build a component directly from an existingthermosteam.Chemical.from_chemical()is now a thin wrapper around it, with unchanged behavior.Documented the
ignore_inaccurate_molar_weightandadjust_MW_to_measured_asoptions ofcompile(), and substantially revised the topical tutorials.
1.5.0¶
All LCA registry types (
ImpactIndicator,ImpactItem,Construction,Transportation) are now isolated per flowsheet. Switching between systems viaset_flowsheet()atomically swaps all four registries, so no manualclear_lca_registries()calls are needed between systems.clear_lca_registries()is deprecated.Added
SanUnit._construction_specs— a class-level tuple of dicts for declaring default construction materials. Specs are resolved lazily byLCAat creation time, soImpactItemobjects do not need to exist when the unit is instantiated.Reorganized unit operations and process models into clearer namespaces.
qsdsan.sanunitsis renamed toqsdsan.unit_operationsand reorganized into three behavior-based sub-namespaces:qsdsan.unit_operations.bst— BioSTEAM-inherited unit operations (mixers, splitters, pumps, heat exchangers, distillation columns, tanks, etc.)qsdsan.unit_operations.static— steady-state QSDsan unit operations (sanitation fixtures, treatment beds, clarifiers, sludge handling, hydrothermal/hydroprocessing units, etc.)qsdsan.unit_operations.dynamic— unit operations with explicit dynamic-state behavior (bioreactors, dynamic influent, junctions, membrane bioreactors, etc.)
qsdsan.processesis renamed toqsdsan.process_models.All existing imports via
qsdsan.sanunitsandqsdsan.processesremain valid for backward compatibility.
Restructured API documentation to mirror the new package layout, with dedicated pages for each sub-namespace.
Bug fixes in
rhos_asm2d():Added
if X_MeOH > 0andif X_MeP > 0guards to the precipitation and redissolution reactions, consistent with the existing guards forX_H,X_PAO, andX_AUT. Without these guards, the BDF solver’s polynomial extrapolation could produce tiny positive floating-point values forX_MeOH, causing spuriousX_MePaccumulation over long simulations.Added a
S_F + S_A > 0guard to the heterotrophic growth substrate-partitioning terms. When the BDF Newton iterations drive both fermentable substrate (S_F) and acetate (S_A) to zero simultaneously, the partition fractionsS_F/(S_F+S_A)andS_A/(S_F+S_A)produce0/0and raise aFloatingPointError; zero substrate correctly implies zero growth.
Multiple bug fixes and improvements to
PolishingFilter:Moved O2 deficit calculation before the effluent split so dissolved oxygen is correctly accounted for in all outlet streams.
Added an aerobic-only guard for air injection: air is now only added when
self.has_pumpisFalseand the unit operates in aerobic mode.Fixed a missing
_freeboardattribute that causedAttributeErroron initialization.Restored the
_design_anaerobicmethod that had been inadvertently removed.Corrected the slab concrete volume formula.
Added a
biomass_IDparameter to allow users to specify which component tracks active biomass.Renamed internal attributes
gas/soluble/solidtogases/solubles/solidsfor consistency with the rest of the codebase.Fixed the condition in
get_digestion_rxnsand corrected the argument order in_refresh_rxns.Fixed a
SanStream.degassingAttributeErrorthat occurred when the polishing filter effluent was a plainSanStream.Fixed an O2 double-counting error in
air_outthat produced a ~0.6% mass-balance error.
Fixed
HydraulicDelay: added missing_update_stateand_update_dstatemethods so the unit correctly propagates state during dynamic simulation.Added a deprecation warning to
SimpleTEAto guide users toward the updated TEA interface.Lazy-imported optional heavy dependencies (
SALib,seaborn,chaospy,sympy) so thatimport qsdsanno longer pays the startup cost of those libraries unless they are actually used.Added a GitHub Actions release workflow that automatically publishes to PyPI and creates a GitHub release when a
v*.*.*tag is pushed.
1.4.0¶
A lot of the updates have been focused on the dynamic simulation, now the open-loop Benchmark Simulation Model No. 2 (BSM2) configuration has been implemented with new process models and unit operation including
qsdsan.processes.ADM1pqsdsan.processes.ADM1_p_extensionqsdsan.processes.ModifiedADM1qsdsan.processes.mASM2dqsdsan.sanunits.IdealClarifierqsdsan.sanunits.PrimaryClarifierqsdsan.sanunits.PrimaryClarifierBSM2qsdsan.sanunits.GasExtractionMembraneqsdsan.sanunits.Thickenerqsdsan.sanunits.Centrifugeqsdsan.sanunits.Incineratorqsdsan.sanunits.BatchExperimentqsdsan.sanunits.PFRqsdsan.sanunits.BeltThickenerqsdsan.sanunits.SludgeCentrifugeqsdsan.sanunits.SludgeThickener
New publications
Feng et al., Environmental Science & Technology, on the sustainability of hydrothermal liquefaction (HTL) for resource recovery from a range of wet organic wastes.
1.3.0¶
Enhance and use QSDsan’s capacity for dynamic simulation for emerging technologies and benchmark configurations (see EXPOsan METAB and PM2 (on the algae branch, still under development) modules).
New publications
The paper introducing DMsan, the package developed for decision-making of sanitation and resource recovery technologies, is published in ACS Environmental Au!
QSDsan was used to evaluate the sustainability of the NEWgenerator system as in this paper on ACS Environmental Au!
New modules
qsdsan.processes.KineticReaction
QSDsannow has a website to host all of the resources!QSDsan’s documentation is getting a new look!Add new units to enable dynamic simulation of systems with multiple process models. Check out
qsdsan.sanunits.Junction,qsdsan.sanunits.ADMtoASM,qsdsan.sanunits.ASMtoADMand their use in the interface system demo.In online testing, we dropped the test for Python 3.8 and added Python 3.10. The main developing environment for QSDsan is 3.9.
1.2.0¶
The QSDsan paper is accepted by Environmental Science: Water Research & Technology!
The first paper using QSDsan for the design of sanitation is accepted by ACS Environmental Au! Read the Biogenic Refinery paper and check out the system module in
QSDsan/EXPOsan.Added multiple systems (including their unit operations), check out the details on the Developed System page!
Biogenic Refinery
Eco-San
Reclaimer
Added the anaerobic digestion model no. 1 (ADM1) process model and the unit
qsdsan.sanunits.AnaerobicCSTR, the corresponding system can be found in EXPOsan.Other new unit operations:
Encapsulation Bioreactors:
qsdsan.sanunits.CH4Eqsdsan.sanunits.H2E
1.1.0¶
Fully tested dynamic simulation capacity, refer to the BSM1 system in EXPOsan for an example implementation.
Added many new
qsdsan.SanUnitand reorganized package/documentation structure, new unit operations include:qsdsan.sanunits.AnMBRqsdsan.sanunits.CHPqsdsan.sanunits.InternalCirculationRxqsdsan.sanunits.SludgeHandlingqsdsan.sanunits.BeltThickenerqsdsan.sanunits.SludgeCentrifuge
qsdsan.sanunits.PolishingFilterqsdsan.sanunits.WWTpump
Continue to enhance documentation (e.g.,
qsdsan.Process, qsdsan.stats, util functions).
1.0.0¶
Official release of QSDsan v1.0.0!
Added system-wise dynamic simulation capacity. To use the dynamic simulation function, a unit needs to have several supporting methods to initialize its state and compile ordinary differential equations (ODEs), refer to the units included in the BSM1 system below for usage, documentation and tutorial will be coming soon!
Developed the benchmark simulation system no.1 (BSM1) model on EXPOsan with comparison against the MATLAB/Simulink model developed by the International Water Association (IWA) Task Group on Benchmarking of Control Strategies. See the README for details
Significantly expanded the tutorials with demo videos on YouTube. Now tutorials cover all non-dynamic major classes (tutorials on dynamic classes will be included in the next major release).
0.3.0¶
Now LCA data can be imported from external databases using the newly made BW2QSD package.
New subclasses of
qsdsan.SanUnit:qsdsan.sanunits.Clarifierqsdsan.sanunits.CSTRqsdsan.sanunits.ElectrochemicalCellusing the followingqsdsan.Equipment:
New subclasses of
qsdsan.Process:qsdsan.processes.DiffusedAerationqsdsan.processes.ASM1qsdsan.processes.ASM2d
Updated
qsdsan.SanUnitso that it can be initialized with any ofthermosteam.Stream,qsdsan.SanStream, orqsdsan.WasteStream.These three classes can now be mixed.
Added
qsdsan.SanStreamfor non-waste streams (e.g., gases).Updated the
add_OPEXattribute ofqsdsan.SanUnitandsystem_add_OPEXattribute ofqsdsan.SimpleTEAso that they takedictas the default to allow display of multiple additional operating expenses.Split the
systemsmodule into an individual package EXPOsan.Now using
thermosteam.utils.Registryto manageqsdsan.ImpactIndicatorandqsdsan.ImpactItem.Added AppVeyor CI.
Renamed the
masterbranch tomain.
0.2.0¶
Added
qsdsan.Process,qsdsan.Processes, andqsdsan.CompiledProcessesclasses for stoichiometric process and its kinetics.Added an
qsdsan.Equipmentclass for design and costing of unit equipment.For the
statsmodule:More statistical tests:
qsdsan.stats.fast_analysis()for (extended) Fourier amplitude sensitivity test (FAST) and random balance design (RBD) FAST.qsdsan.stats.morris_till_convergence()to run Morris analysis until the results converge.Added Kendall’s tau and Kolmogorov–Smirnov test to
qsdsan.stats.get_correlations().
Plotting functions to visualize all test results:
qsdsan.stats.plot_uncertainties()for results from uncertainty analysis as different 1D or 2D plots.qsdsan.stats.plot_correlations()for results fromqsdsan.stats.get_correlation().Bar plot option for
qsdsan.stats.plot_morris_results().qsdsan.stats.plot_morris_convergence()to plot \({\mu^*}\) against the number of trajectories.qsdsan.stats.plot_fast_results()for results from FAST and/or RBD-FAST analyses.qsdsan.stats.plot_sobol_results()for results from Sobol analysis.
Changed all .csv data files to .tsv so that they can be viewed on GitHub.
Added more clear guidelines on contribution and a author list in the document.
0.1.0¶
Added a
statsmodule including:Pearson and Spearman correlations:
qsdsan.stats.get_correlations().Morris One-at-A-Time (OAT) screening method:
qsdsan.stats.morris_analysis().Also added a function for plotting:
qsdsan.stats.plot_morris_results().
Sobol sensitivity analysis:
qsdsan.stats.sobol_analysis().
Added all uncertainty parameters for all of the scenarios in the bwaise system, also added demonstrative Morris and Sobol analysis.
LCA.get_normalized_impacts()was replaced byqsdsan.LCA.get_allocated_impacts()forqsdsan.LCAto enable flexible allocation options.Reformatted all documents, added instructions on documentation.
Added brief instructions on contributing and code of conduct.
Updated UML diagram.
0.0.3¶
More flexible setting of
qsdsan.ImpactItemforqsdsan.WasteStream.Add status badge to README.rst
Add CHANGELOG.rst
Tutorial updates:
- New:
qsdsan.TEAandqsdsan.LCA
- Updated:
qsdsan.SanUnitandqsdsan.System
0.0.2¶
Added the all three sanitation scenarios as described in Trimmer et al., including uncertainty/sensitivity analyses with tutorial.
Inclusion of GPX models for estimation of
qsdsan.WasteStreamproperties.New classes:
All units in Trimmer et al.
Added descriptors (
qsdsan.utils.descriptors) and decorators (qsdsan.utils.checkers) to check user-input values.qsdsan.utils.setters.AttrSetter,qsdsan.utils.setters.DictAttrSetter, andqsdsan.utils.getters.FuncGetterfor batch-setting of uncertainty analysis parameters.
Added
save_report()function toqsdsan.LCAfor report exporting.
0.0.1¶
First public release.