def interpolate_wo(wo_low, wo_high, parameter, h=0.01, tag=None): """Interpolates between two water-oil curves. The saturation endpoints for the curves must be known by the objects. They can be estimated by estimate_sorw() etc. or can be set manually for finer control. The interpolation algorithm is different left and right for saturation endpoints, and saturation endpoints are interpolated individually. Arguments: wo_low (WaterOil): a "low" case wo_high (WaterOil): a "high" case parameter (float): Between 0 and 1. 0 will return the low case, 1 will return the high case. Any number in between will return an interpolated curve h (float): Saturation step-size in interpolant. If defaulted, a value smaller than in the input curves are used, to preserve information. tag (string): Tag to associate to the constructed object. If None it will be automatically filled. Set to empty string to ensure no tag. Returns: A new oil-water curve """ # Warning: Almost code duplication with corresponding _go function assert isinstance(wo_low, pyscal.WaterOil) assert isinstance(wo_high, pyscal.WaterOil) assert 0 <= parameter <= 1 # Extrapolation is refused, but perhaps later implemented with truncation to (0,1) # Running fast mode if both interpolants have fast mode if wo_low.fast and wo_high.fast: fast = True else: fast = False # Constructs functions that works on normalized saturation interval krw1, kro1 = normalize_nonlinpart_wo(wo_low) krw2, kro2 = normalize_nonlinpart_wo(wo_high) pc1 = normalize_pc(wo_low) pc2 = normalize_pc(wo_high) # Construct a function that can be applied to both relperm values # and endpoints def weighted_value(a, b): return a * (1.0 - parameter) + b * parameter # Interpolate saturation endpoints swl_new = weighted_value(wo_low.swl, wo_high.swl) swcr_new = weighted_value(wo_low.swcr, wo_high.swcr) sorw_new = weighted_value(wo_low.sorw, wo_high.sorw) # Interpolate kr at saturation endpoints krwmax_new = weighted_value(wo_low.table["krw"].max(), wo_high.table["krw"].max()) krwend_new = weighted_value(krw1(1), krw2(1)) kroend_new = weighted_value(kro1(1), kro2(1)) # Construct the new WaterOil object, with interpolated # endpoints: wo_new = pyscal.WaterOil(swl=swl_new, swcr=swcr_new, sorw=sorw_new, h=h, fast=fast) # Add interpolated relperm data in nonlinear parts: wo_new.table["krw"] = weighted_value(krw1(wo_new.table["swn"]), krw2(wo_new.table["swn"])) wo_new.table["krow"] = weighted_value(kro1(wo_new.table["son"]), kro2(wo_new.table["son"])) wo_new.set_endpoints_linearpart_krw(krwend=krwend_new, krwmax=krwmax_new) wo_new.set_endpoints_linearpart_krow(kroend=kroend_new) # We need a new fit-for-purpose normalized swnpc, that ignores # the initial swnpc (swirr-influenced) wo_new.table["swn_pc_intp"] = ( wo_new.table["sw"] - wo_new.table["sw"].min()) / ( wo_new.table["sw"].max() - wo_new.table["sw"].min()) wo_new.table["pc"] = weighted_value(pc1(wo_new.table["swn_pc_intp"]), pc2(wo_new.table["swn_pc_intp"])) wo_new.tag = _interpolate_tags(wo_low, wo_high, parameter, tag) return wo_new
def main(): """Used for invocation on the command line""" parser = get_parser() args = parser.parse_args() warnings.warn("gen_satfunc is deprecated, use pyscal", FutureWarning) logger.setLevel(logging.INFO) if not Path(args.config_file).exists(): sys.exit(f"Could not find the configuration file: {args.config_file}") output = "" for line in open(args.config_file).readlines(): tmp = line.strip() if not tmp[0:2] == "--" and len(tmp) > 0: if tmp[0:7] == "RELPERM": # Parse relperm parameters from the rest of the line: relperm_input = tuple(tmp[8:].split("--")[0].split()) relperm_input = [float(i) for i in relperm_input] if len(relperm_input) < 9: logger.error("Too few relperm parameters in line:\n%s", line) raise ValueError("Erroneous relperm parameters") # Unpack parameter list to explicitly named parameters: (Lw, Ew, Tw, Lo, Eo, To, Sorw, Swl, Krwo) = relperm_input[0:9] if len(relperm_input) > 9: num_sw_steps = relperm_input[9] else: num_sw_steps = 20 wo = pyscal.WaterOil(h=1.0 / (num_sw_steps + 2), sorw=Sorw, swl=Swl) wo.add_LET_oil(Lo, Eo, To, kroend=1) wo.add_LET_water(Lw, Ew, Tw, krwend=Krwo) if 10 < len(relperm_input) < 15: logger.error("Too few parameter for pc in line:\n%s", line) raise ValueError("Erroneous pc parameters") if len(relperm_input) == 15: (PERM, PORO, a, b, sigma_costau) = relperm_input[10:15] wo.add_normalized_J(a=a, b=b, poro=PORO, perm=PERM, sigma_costau=sigma_costau) output += wo.SWOF(header=False) elif tmp[0:7] == "COMMENT": logger.info("Printing comment") comment = tmp[8:].split("--")[0] output = output + "--" + comment + "\n" elif tmp[0:4] == "SWOF": logger.info("Generating SWOF table") output = output + "SWOF\n" elif tmp[0:4] == "SGOF": logger.info("Generating SGOF table") output = output + "SGOF\n" else: raise ValueError('Error while interpreting line: "%s"' % line.strip()) logger.info("Writing output file...") Path(args.output_file).write_text(output) logger.info("Done")