Specifying user parameters for GC SAFT methods #352
-
|
Hi all I just wanted to know if it would be possible to specify name-value pairs for GC SAFT parameters similar to that when using non-GC methods, something like Any help will be much appreciated! |
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 4 replies
-
|
Hello, On the parameter inputs, the answer is that we don't have a clean interface to passing GC user parameters. you see, when we create a GC model we do the following things internally:
What does this mean? you can technically pass GC parameters directly if you know the order of your unique groups beforehand. On the incompatibility of your function with ForwardDiff, this is expected. The use of parametric number types is restricted (as of now) to |
Beta Was this translation helpful? Give feedback.
-
|
Hi all I did a deep dive into the source code and think I have a way to do this, without changing much to the current code. Ultimately we only want to change the parameters (pure, mixture or assoc), whilst keeping the sites, molecular weights, the decomposition of the compounds into their functional groups and To this end, we can create a new definition for the function SAFTgammaMie(groups::GroupParam, params::Dict{String,ClapeyronParam};
idealmodel = BasicIdeal,
ideal_userlocations = String[],
reference_state = nothing,
verbose = false,
epsilon_mixing = :default,
assoc_options = AssocOptions())
sites = params["sites"]
components = groups.components
... # remaining code in the existing definition
endIf this is incorporated, for efficiency we can redefine the current defintion to: function SAFTgammaMie(components;
idealmodel = BasicIdeal,
userlocations = String[],
group_userlocations = String[],
ideal_userlocations = String[],
reference_state = nothing,
verbose = false,
epsilon_mixing = :default,
assoc_options = AssocOptions())
groups = GroupParam(components, ["SAFT/SAFTgammaMie/SAFTgammaMie_groups.csv"]; group_userlocations = group_userlocations,verbose = verbose)
params = getparams(groups, ["SAFT/SAFTgammaMie","properties/molarmass_groups.csv"]; userlocations = userlocations, verbose = verbose)
return SAFTgammaMie(groups, params;
idealmodel = idealmodel,
ideal_userlocations = ideal_userlocations ,
reference_state = reference_state,
verbose = verbose,
epsilon_mixing = epsilon_mixing,
assoc_options = assoc_options)
endWe can then generate our own Some skeleton code is as follows: using Clapeyron
groulist = ["comp1", "comp2", "comp3", ...]; # compi should be replaced by the compounds considered
groups = GroupParam(grouplist, [csv_to_SAFTgammaMie_groups]); # the default csv_to_SAFTgammaMie_groups = "SAFT/SAFTgammaMie/SAFTgammaMie_groups.csv". The comps should be defined here in terms of their groups
options = ParamOptions(;ignore_missing_singleparams=["sigma"]); # in this case assume sigma is missing.
params = getparams(groups, [path_to_skeleton_like_unlike_and_assoc_csvs_as_well_as_molar_masses_of_groups],options); # 'vst' should always be known in the like file.The params["epsilon"].values[1,2] = params["epsilon"].values[2,1] = some_val; # assuming symmetric values
params["epsilon"].ismissingvalues[1,2] = params["epsilon"].ismissingvalues[2,1] = false; Assoc params are a bit more complicated as these are constructed using the compressed4DMatrix. The relevant field to consider in the idx_group1_outer = findfirst(unique_groups .== group1); # find the group index = outer_index
idx_group2_outer = findfirst(unique_groups .== group2);
idx_group1_inner = findfirst(params["sites"].sites[idx_group1_outer] .== "e1"); # find the site index in the group = inner_index
idx_group2_inner = findfirst(params["sites"].sites[idx_group2_outer] .== "H");
outer_index_app = [(idx_group1_outer, idx_group2_outer)]; # outer index to append
inner_index_app = [(idx_group1_inner, idx_group2_inner)]; # inner index to append
append!(params["epsilon_assoc"].values.values, val_epsilon_assoc);
append!(params["epsilon_assoc"].values.outer_indices, outer_indices_app);
append!(params["epsilon_assoc"].values.inner_indices, inner_indices_app);
append!(params["bondvol"].values.values, val_bondvol);
append!(params["bondvol"].values.outer_indices, outer_indices_app);
append!(params["bondvol"].values.inner_indices, inner_indices_app);The final step is then to call the This implementation should circumvent the issues associated with autodiff for parameter estimation (should not be limited to SAFT since this is generalizable to other GC approaches). This approach is probably sub-optimal but should be fine for now until a better solution comes up? Something I am uncertain of however is if the symmetry between sites are maintained in the GC implemetations? That is if we have for instance group1 with [H, e1] sites and group2 with [H,e1] sites, if we assign some value to Many thanks |
Beta Was this translation helpful? Give feedback.
-
|
Hello, Lots to unpack in your comment. First of all, i've been working on supporting AD on SAFTgammaMie and the last release is almost ready for that. there is already another user of this feature, and we are debugging the final kinks in #366. I mentioned parametric because when calculating a gradient of a function with respect to SAFTgammaMie parameters, you are actually asking the model to hold On the last release, i separated some fields in SAFTgammaMie that were used in EoS Evaluation ( Now, on the strategy presented here. Seems like a great idea. We already have functions to build skeletons of parameters. For example, Calling On On SAFTgammaMie, additionally, we do a transformation of the sites from a group base to a component base. this allows us to use the same association solver for all SAFTs. (that is the main function of the inner For most EoS. #pseudocode, we can do this efficiently with a generated function for almost all types, and manually do this for types that don't conform to the API.
function (::Type{P})(compdata::Union{GroupParam,Vector{String},sites::Union{nothing,SiteParam}) where P <: Clapeyron.EoSParam
res = []
comps = compdata isa GroupParam ? : compdata.flattenedgroups : compdata
for name in fieldnames(P)
f = fieldtype(P,name)
if f isa AssocParam
push!(res,f(String(name), sites)
else
push!(res,f(String(name), comps )
end
end
return P(res...)
end
function (::Type{P})(compdata::Union{GroupParam,Vector{String}) where P <: Clapeyron.EoSParam
return P(compdata,nothing)
endNow, we have a skeleton, and we can fill it with data. we do have some utility functions to do this:
Finally, to answer some questions.
No, we don't assume this in GC nor component-based models, you need to explicitly add both interactions. Happy to hear what do you think of this. |
Beta Was this translation helpful? Give feedback.
Hello,
Lots to unpack in your comment.
First of all, i've been working on supporting AD on SAFTgammaMie and the last release is almost ready for that. there is already another user of this feature, and we are debugging the final kinks in #366. I mentioned parametric because when calculating a gradient of a function with respect to SAFTgammaMie parameters, you are actually asking the model to hold
ForwardDiff.Dualnumbers. that was not possible until the last release. So it is a good step towards what you want to do.On the last release, i separated some fields in SAFTgammaMie that were used in EoS Evaluation (
mixed_segment::MixedSegmentGCParam). So there is additional work to do in terms …