diff --git a/examples/2d/pod/cookie_single_pod.py b/examples/2d/pod/cookie_single_pod.py index 6f4ab5c..0efdfd4 100644 --- a/examples/2d/pod/cookie_single_pod.py +++ b/examples/2d/pod/cookie_single_pod.py @@ -1,144 +1,134 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ CookieEngineSingle as CES -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 5 size = 1 show_sample = True show_norm = True clip = -1 #clip = .4 #clip = .6 Delta = -10 MN = 15 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 PODTol = 1e-6 samples = "centered" -samples = "distributed" +samples = "standard" algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" sampling = "random" -if samples == "distributed": +if samples == "standard": radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 1. radialWeight = [rW0] * 2 assert Delta <= 0 if size == 1: # below mu0 = [20 ** .5, 1. ** .5] mutar = [20.5 ** .5, 1.05 ** .5] murange = [[18.5 ** .5, .85 ** .5], [21.5 ** .5, 1.15 ** .5]] aEff = 1.#25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, aEff*murange[0][1] + bEff*murange[1][1]], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, aEff*murange[1][1] + bEff*murange[0][1]]] kappa = 20. ** .5 theta = - np.pi / 6. n = 30 Rad = 1. L = np.pi nX = 2 nY = 1 solver = CES(kappa = kappa, theta = theta, n = n, R = Rad, L = L, nX = nX, nY = nY, mu0 = mu0, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.)] * 2 -rescalingInv = [lambda x: np.power(x, .5)] * 2 +rescalingExp = [2.] * 2 if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight - method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R - method = RI + method = RI else: #if algo == "RB": params = {'R':(MN + 2 + Delta) * (MN + 1 + Delta) // 2, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD - elif samples == "centered": + if samples == "centered": params['S'] = R - method = RBD + method = RB -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) -if samples == "distributed": approx.samplingEngine.allowRepeatedSamples = False +if samples == "standard": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: L = mutar[1] approx.plotApprox(mutar, name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, name = 'res', homogeneized = False, what = "REAL") appErr = approx.normErr(mutar) solNorm = approx.normHF(mutar) resNorm = approx.normRes(mutar) RHSNorm = approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational" and approx.N > 0: from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 2.], clip = clip) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 25, [2., 2.], clip = clip, relative = False) diff --git a/examples/2d/pod/fracture_pod.py b/examples/2d/pod/fracture_pod.py index 957eb08..646274d 100644 --- a/examples/2d/pod/fracture_pod.py +++ b/examples/2d/pod/fracture_pod.py @@ -1,277 +1,280 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ MembraneFractureEngine as MFE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD -from rrompy.reduction_methods.pivoting import RBDistributedPivoted as RBP -from rrompy.reduction_methods.pivoting import \ - RationalInterpolantPivotedPoleMatching as RIPPM +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.reduction_methods.pivoted import RationalInterpolantPivoted as RIP +from rrompy.reduction_methods.pivoted import ReducedBasisPivoted as RBP +from rrompy.reduction_methods.pole_matching import \ + RationalInterpolantPoleMatching as RIPM +from rrompy.reduction_methods.pole_matching import \ + ReducedBasisPoleMatching as RBPM from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) -verb = 5 +verb = 70 size = 2 show_sample = False show_norm = True -clip = -1 -#clip = .4 -#clip = .6 Delta = 0 -MN = 5 +MN = 8 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 -PODTol = 1e-8 +PODTol = 1e-4 SPivot = [MN + 1, 4] -MMarginal = SPivot[1] - 2 -matchingWeight = 10. +MMarginal = SPivot[1] - 1 +matchingWeight = 1. +cutOffTolerance = 1. * np.inf +cutOffType = "MAGNITUDE" samples = "centered" -samples = "distributed" +samples = "standard" samples = "pivoted" +samples = "pole matching" algo = "rational" algo = "RB" sampling = "quadrature" sampling = "quadrature_total" #sampling = "random" samplingM = "quadrature" #samplingM = "quadrature_total" #samplingM = "random" -if samples == "distributed": - radial = 0 -# radial = "gaussian" -# radial = "thinplate" -# radial = "multiquadric" - rW0 = 5. - radialWeight = [rW0] * 2 -if samples == "pivoted": +if samples in ["standard", "pivoted", "pole matching"]: radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 5. radialWeight = [rW0] +if samples in ["pivoted", "pole matching"]: radialM = 0 - radialM = "gaussian" +# radialM = "gaussian" # radialM = "thinplate" # radialM = "multiquadric" rMW0 = 2. radialWeightM = [rMW0] assert Delta <= 0 if size == 1: # below mu0 = [40 ** .5, .4] mutar = [45 ** .5, .4] murange = [[30 ** .5, .3], [50 ** .5, .5]] elif size == 2: # top mu0 = [40 ** .5, .6] mutar = [45 ** .5, .6] murange = [[30 ** .5, .5], [50 ** .5, .7]] elif size == 3: # interesting mu0 = [40 ** .5, .5] mutar = [45 ** .5, .5] murange = [[30 ** .5, .3], [50 ** .5, .7]] elif size == 4: # wide_low mu0 = [40 ** .5, .2] mutar = [45 ** .5, .2] murange = [[10 ** .5, .1], [70 ** .5, .3]] elif size == 5: # wide_hi mu0 = [40 ** .5, .8] mutar = [45 ** .5, .8] murange = [[10 ** .5, .7], [70 ** .5, .9]] elif size == 6: # top_zoom mu0 = [50 ** .5, .8] mutar = [55 ** .5, .8] murange = [[40 ** .5, .7], [60 ** .5, .9]] elif size == 7: # huge mu0 = [50 ** .5, .5] mutar = [55 ** .5, .5] murange = [[10 ** .5, .2], [90 ** .5, .8]] elif size == 11: #L below mu0 = [110 ** .5, .4] mutar = [115 ** .5, .4] murange = [[90 ** .5, .3], [130 ** .5, .5]] elif size == 12: #L top mu0 = [110 ** .5, .6] mutar = [115 ** .5, .6] murange = [[90 ** .5, .5], [130 ** .5, .7]] elif size == 13: #L interesting mu0 = [110 ** .5, .5] mutar = [115 ** .5, .5] murange = [[90 ** .5, .3], [130 ** .5, .7]] elif size == 14: #L belowbelow mu0 = [110 ** .5, .2] mutar = [115 ** .5, .2] murange = [[90 ** .5, .1], [130 ** .5, .3]] elif size == 15: #L toptop mu0 = [110 ** .5, .8] mutar = [115 ** .5, .8] murange = [[90 ** .5, .7], [130 ** .5, .9]] elif size == 16: #L interestinginteresting mu0 = [110 ** .5, .5] mutar = [115 ** .5, .6] murange = [[90 ** .5, .1], [130 ** .5, .9]] elif size == 17: #L interestingtop mu0 = [110 ** .5, .7] mutar = [115 ** .5, .6] murange = [[90 ** .5, .5], [130 ** .5, .9]] elif size == 18: #L interestingbelow mu0 = [110 ** .5, .3] mutar = [115 ** .5, .4] murange = [[90 ** .5, .1], [130 ** .5, .5]] elif size == 100: # tiny mu0 = [32.5 ** .5, .5] mutar = [34 ** .5, .5] murange = [[30 ** .5, .3], [35 ** .5, .7]] aEff = 1.#25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, aEff*murange[0][1] + bEff*murange[1][1]], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, aEff*murange[1][1] + bEff*murange[0][1]]] H = 1. L = .75 delta = .05 n = 20 solver = MFE(mu0 = mu0, H = H, L = L, delta = delta, n = n, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.), lambda x: x] -rescalingInv = [lambda x: np.power(x, .5), lambda x: x] +rescalingExp = [2., 1.] if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R method = RI - elif samples == "pivoted": + elif samples in ["pivoted", "pole matching"]: params['S'] = [SPivot[0]] params['SMarginal'] = [SPivot[1]] params['MMarginal'] = MMarginal params['polybasisPivot'] = "CHEBYSHEV" params['polybasisMarginal'] = "MONOMIAL" - params['matchingWeight'] = matchingWeight params['radialBasisPivot'] = radial params['radialBasisMarginal'] = radialM params['radialBasisWeightsPivot'] = radialWeight params['radialBasisWeightsMarginal'] = radialWeightM - method = RIPPM + if samples == "pivoted": + method = RIP + else: + params['matchingWeight'] = matchingWeight + params['cutOffTolerance'] = cutOffTolerance + params["cutOffType"] = cutOffType + method = RIPM else: #if algo == "RB": params = {'R':(MN + 2 + Delta) * (MN + 1 + Delta) // 2, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD + if samples == "standard": + method = RB elif samples == "centered": params['S'] = R - method = RBD - elif samples == "pivoted": + method = RB + elif samples in ["pivoted", "pole matching"]: params['S'] = [SPivot[0]] params['SMarginal'] = [SPivot[1]] params['MMarginal'] = MMarginal params['polybasisMarginal'] = "MONOMIAL" params['radialBasisMarginal'] = radialM params['radialBasisWeightsMarginal'] = radialWeightM method = RBP + if samples == "pivoted": + method = RBP + else: + params['matchingWeight'] = matchingWeight + params['cutOffTolerance'] = cutOffTolerance + params["cutOffType"] = cutOffType + method = RBPM -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) -elif samples == "pivoted": + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) +elif samples in ["pivoted", "pole matching"]: if sampling == "quadrature": params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "CHEBYSHEV") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "GAUSSLEGENDRE") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "UNIFORM") elif sampling == "quadrature_total": params['samplerPivot'] = QST([murange[0][0], murange[1][0]], "CHEBYSHEV") else: # if sampling == "random": params['samplerPivot'] = RS([murange[0][0], murange[1][0]], "HALTON") if samplingM == "quadrature": params['samplerMarginal'] = QS([murange[0][1], murange[1][1]], "UNIFORM") elif samplingM == "quadrature_total": params['samplerMarginal'] = QST([murange[0][1], murange[1][1]], "CHEBYSHEV") else: # if samplingM == "random": params['samplerMarginal'] = RS([murange[0][1], murange[1][1]], "HALTON") -if samples != "pivoted": +if samples not in ["pivoted", "pole matching"]: approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) else: approx = method(solver, mu0 = mu0, directionPivot = [0], approxParameters = params, verbosity = verb) if samples != "centered": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: import ufl import fenics as fen from rrompy.solver.fenics import affine_warping L = mutar[1] y = fen.SpatialCoordinate(solver.V.mesh())[1] warp1, warpI1 = affine_warping(solver.V.mesh(), np.array([[1, 0], [0, 2. * L]])) warp2, warpI2 = affine_warping(solver.V.mesh(), np.array([[1, 0], [0, 2. - 2. * L]])) warp = ufl.conditional(ufl.ge(y, 0.), warp1, warp2) warpI = ufl.conditional(ufl.ge(y, 0.), warpI1, warpI2) approx.plotApprox(mutar, [warp, warpI], name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, [warp, warpI], name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, [warp, warpI], name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, [warp, warpI], name = 'res', # homogeneized = False, what = "REAL") appErr = approx.normErr(mutar) solNorm = approx.normHF(mutar) resNorm = approx.normRes(mutar) RHSNorm = approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) +approx.verbosity = 5 from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, - 200, [2., 1.], clip = clip) + 200, [2., 1.]) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( - murange, murangeEff, approx, mu0, 25, - [2., 1.], clip = clip, relative = True, + murange, murangeEff, approx, mu0, 50, + [2., 1.], relative = True, nobeta = True) print(np.sort(approx.getPoles([None, .5]) ** 2.)) diff --git a/examples/2d/pod/fracture_pod_nodomain.py b/examples/2d/pod/fracture_pod_nodomain.py index afc7629..f43decc 100644 --- a/examples/2d/pod/fracture_pod_nodomain.py +++ b/examples/2d/pod/fracture_pod_nodomain.py @@ -1,182 +1,172 @@ import numpy as np from rrompy.hfengines.linear_problem import MembraneFractureEngineNoDomain \ as MFEND -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 5 size = 1 show_sample = True show_norm = True ignore_forcing = True ignore_forcing = False clip = -1 #clip = .4 #clip = .6 homogeneize = False #homogeneize = True Delta = 0 MN = 6 R = MN + 1 S = R samples = "centered" -samples = "distributed" +samples = "standard" algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" sampling = "random" -if samples == "distributed": +if samples == "standard": radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" radialWeight = [2.] assert Delta <= 0 if size == 1: # below mu0Aug = [40 ** .5, .4] mu0 = mu0Aug[0] mutar = 45 ** .5 murange = [[30 ** .5], [50 ** .5]] elif size == 2: # top mu0Aug = [40 ** .5, .6] mu0 = mu0Aug[0] mutar = 45 ** .5 murange = [[30 ** .5], [50 ** .5]] elif size == 3: # interesting mu0Aug = [40 ** .5, .5] mu0 = mu0Aug[0] mutar = 45 ** .5 murange = [[30 ** .5], [50 ** .5]] elif size == 4: # wide_low mu0Aug = [40 ** .5, .2] mu0 = mu0Aug[0] mutar = 45 ** .5 murange = [[10 ** .5], [70 ** .5]] elif size == 5: # wide_hi mu0Aug = [40 ** .5, .8] mu0 = mu0Aug[0] mutar = 45 ** .5 murange = [[10 ** .5], [70 ** .5]] elif size == 6: # top_zoom mu0Aug = [50 ** .5, .8] mu0 = mu0Aug[0] mutar = 55 ** .5 murange = [[40 ** .5], [60 ** .5]] aEff = 1.#25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5]] H = 1. L = .75 delta = .05 n = 20 solver = MFEND(mu0 = mu0Aug, H = H, L = L, delta = delta, n = n, verbosity = verb) -rescaling = lambda x: np.power(x, 2.) -rescalingInv = lambda x: np.power(x, .5) +rescalingExp = 2. if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight - method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R - method = RI + method = RI else: #if algo == "RB": params = {'R':R, 'S':S, 'POD':True} - if samples == "distributed": - method = RBD - elif samples == "centered": + if samples == "centered": params['S'] = R - method = RBD + method = RB -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb, homogeneized = homogeneize) -if samples == "distributed": approx.samplingEngine.allowRepeatedSamples = False +if samples == "standard": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: import ufl import fenics as fen from rrompy.solver.fenics import affine_warping L = solver.lFrac y = fen.SpatialCoordinate(solver.V.mesh())[1] warp1, warpI1 = affine_warping(solver.V.mesh(), np.array([[1, 0], [0, 2. * L]])) warp2, warpI2 = affine_warping(solver.V.mesh(), np.array([[1, 0], [0, 2. - 2. * L]])) warp = ufl.conditional(ufl.ge(y, 0.), warp1, warp2) warpI = ufl.conditional(ufl.ge(y, 0.), warpI1, warpI2) approx.plotApprox(mutar, [warp, warpI], name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, [warp, warpI], name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, [warp, warpI], name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, [warp, warpI], name = 'res', # homogeneized = False, what = "REAL") appErr = approx.normErr(mutar, homogeneized = homogeneize) solNorm = approx.normHF(mutar, homogeneized = homogeneize) resNorm = approx.normRes(mutar, homogeneized = homogeneize) RHSNorm = approx.normRHS(mutar, homogeneized = homogeneize) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational": from plot_zero_set import plotZeroSet1 muZeroVals, Qvals = plotZeroSet1(murange, murangeEff, approx, mu0, 1000, 2.) if show_norm: solver._solveBatchSize = 10 from plot_inf_set import plotInfSet1 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet1( murange, murangeEff, approx, mu0, 200, 2., relative = False, normalizeDen = True) print(approx.getPoles() ** 2.) diff --git a/examples/2d/pod/matrix_passive_pod.py b/examples/2d/pod/matrix_passive_pod.py index 9ccfd7b..7d3e9d7 100644 --- a/examples/2d/pod/matrix_passive_pod.py +++ b/examples/2d/pod/matrix_passive_pod.py @@ -1,197 +1,209 @@ import numpy as np from rrompy.hfengines.linear_problem.tridimensional import \ MatrixDynamicalPassive as MDP -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD -from rrompy.reduction_methods.pivoting import RationalInterpolantPivoted as RIP -from rrompy.reduction_methods.pivoting import RBDistributedPivoted as RBP -from rrompy.reduction_methods.pivoting import \ - RationalInterpolantPivotedPoleMatching as RIPPM +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.reduction_methods.pivoted import RationalInterpolantPivoted as RIP +from rrompy.reduction_methods.pivoted import ReducedBasisPivoted as RBP +from rrompy.reduction_methods.pole_matching import \ + RationalInterpolantPoleMatching as RIPM +from rrompy.reduction_methods.pole_matching import \ + ReducedBasisPoleMatching as RBPM from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) -verb = 5 +verb = 10 size = 3 show_sample = True show_norm = True Delta = 0 MN = 7 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 PODTol = 1e-6 SPivot = [MN + 1, 3] MMarginal = SPivot[1] - 1 samples = "centered" -samples = "distributed" +samples = "standard" samples = "pivoted" samples = "pole matching" algo = "rational" #algo = "RB" sampling = "quadrature" #sampling = "quadrature_total" #sampling = "random" samplingM = "quadrature" #samplingM = "quadrature_total" #samplingM = "random" -if samples in ["distributed", "pivoted", "pole matching"]: +if samples in ["standard", "pivoted", "pole matching"]: radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 10. radialWeight = [rW0] if samples in ["pivoted", "pole matching"]: radialM = 0 - radialM = "gaussian" +# radialM = "gaussian" # radialM = "thinplate" # radialM = "multiquadric" rMW0 = 2. radialWeightM = [rMW0] matchingWeight = 1. +cutOffTolerance = 5. +cutOffType = "POTENTIAL" if size == 1: mu0 = [2.7e2, 20] mutar = [3e2, 25] murange = [[20., 10], [5.2e2, 30]] elif size == 2: mu0 = [2.7e2, 60] mutar = [3e2, 75] murange = [[20., 10], [5.2e2, 110]] elif size == 3: mu0 = [2.7e2, 160] mutar = [3e2, 105] murange = [[20., 10], [5.2e2, 310]] assert Delta <= 0 aEff = 1.#25 bEff = 1. - aEff murangeEff = [[aEff*murange[0][0] + bEff*murange[1][0], aEff*murange[0][1] + bEff*murange[1][1]], [aEff*murange[1][0] + bEff*murange[0][0], aEff*murange[1][1] + bEff*murange[0][1]]] n = 100 b = 10 solver = MDP(mu0 = mu0, n = n, b = b, verbosity = verb) if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R method = RI elif samples in ["pivoted", "pole matching"]: params['S'] = [SPivot[0]] params['SMarginal'] = [SPivot[1]] params['MMarginal'] = MMarginal params['polybasisPivot'] = "CHEBYSHEV" params['polybasisMarginal'] = "MONOMIAL" params['radialBasisPivot'] = radial params['radialBasisMarginal'] = radialM params['radialBasisWeightsPivot'] = radialWeight params['radialBasisWeightsMarginal'] = radialWeightM if samples == "pivoted": method = RIP else: params['matchingWeight'] = matchingWeight - method = RIPPM + params['cutOffTolerance'] = cutOffTolerance + params["cutOffType"] = cutOffType + method = RIPM else: #if algo == "RB": params = {'R':(MN + 2 + Delta) * (MN + 1 + Delta) // 2, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD + if samples == "standard": + method = RB elif samples == "centered": params['S'] = R - method = RBD - elif samples == "pivoted": + method = RB + elif samples in ["pivoted", "pole matching"]: params['R'] = SPivot[0] params['S'] = [SPivot[0]] params['SMarginal'] = [SPivot[1]] - params['MMarginal'] = SPivot[1] - 2 + params['MMarginal'] = MMarginal params['polybasisMarginal'] = "MONOMIAL" params['radialBasisMarginal'] = radialM params['radialBasisWeightsMarginal'] = radialWeightM - method = RBP + if samples == "pivoted": + method = RBP + else: + params['matchingWeight'] = matchingWeight + params['cutOffTolerance'] = cutOffTolerance + params["cutOffType"] = cutOffType + method = RBPM -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": params['sampler'] = QS(murange, "CHEBYSHEV") # params['sampler'] = QS(murange, "GAUSSLEGENDRE") # params['sampler'] = QS(murange, "UNIFORM") elif sampling == "quadrature_total": params['sampler'] = QST(murange, "CHEBYSHEV") else: # if sampling == "random": params['sampler'] = RS(murange, "HALTON") elif samples == "centered": params['sampler'] = MS(murange, points = [mu0]) elif samples in ["pivoted", "pole matching"]: if sampling == "quadrature": params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "CHEBYSHEV") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "GAUSSLEGENDRE") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "UNIFORM") elif sampling == "quadrature_total": params['samplerPivot'] = QST([murange[0][0], murange[1][0]], "CHEBYSHEV") else: # if sampling == "random": params['samplerPivot'] = RS([murange[0][0], murange[1][0]], "HALTON") if samplingM == "quadrature": params['samplerMarginal'] = QS([murange[0][1], murange[1][1]], "UNIFORM") elif samplingM == "quadrature_total": params['samplerMarginal'] = QST([murange[0][1], murange[1][1]], "CHEBYSHEV") else: # if samplingM == "random": params['samplerMarginal'] = RS([murange[0][1], murange[1][1]], "HALTON") if samples not in ["pivoted", "pole matching"]: approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) else: approx = method(solver, mu0 = mu0, directionPivot = [0], approxParameters = params, verbosity = verb) -if samples != "centered": - approx.samplingEngine.allowRepeatedSamples = False +if samples != "centered": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: L = mutar[1] approx.plotApprox(mutar, name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, name = 'res', homogeneized = False, what = "REAL") appErr = approx.normErr(mutar) solNorm = approx.normHF(mutar) resNorm = approx.normRes(mutar) RHSNorm = approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) -if hasattr(approx.trainedModel, "getQVal") and approx.N > 0: +try: from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, - 200, [1., 1]) + 200, [1., 1], polesImTol = 2.) +except: pass if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 50, [1., 1.], relative = False, nobeta = True) print(1.j * approx.getPoles([None, 50.])) diff --git a/examples/2d/pod/square_pod.py b/examples/2d/pod/square_pod.py index 4cf18a2..ecdb2f3 100644 --- a/examples/2d/pod/square_pod.py +++ b/examples/2d/pod/square_pod.py @@ -1,190 +1,194 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ HelmholtzSquareDomainProblemEngine as HSDPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD -from rrompy.reduction_methods.pivoting import \ - RationalInterpolantPivotedPoleMatching as RIPPM +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.reduction_methods.pole_matching import \ + RationalInterpolantPoleMatching as RIPM +from rrompy.reduction_methods.pole_matching import \ + ReducedBasisPoleMatching as RBPM from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 5 size = 7 show_sample = False show_norm = True ignore_forcing = True ignore_forcing = False clip = -1 #clip = .4 #clip = .6 MN = 6 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 SPivot = [MN + 1, 3] MMarginal = SPivot[1] - 2 matchingWeight = 10. samples = "centered" -samples = "distributed" -samples = "pivoted" +samples = "standard" +samples = "pole matching" algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" #sampling = "random" samplingM = "quadrature" #samplingM = "quadrature_total" #samplingM = "random" -if samples == "pivoted": +if samples == "pole matching": radialM = 0 radialM = "gaussian" # radialM = "thinplate" # radialM = "multiquadric" rMW0 = 2. radialWeightM = [rMW0] if size == 1: # small mu0 = [4 ** .5, 1.5 ** .5] mutar = [5 ** .5, 1.75 ** .5] murange = [[2 ** .5, 1. ** .5], [6 ** .5, 2. ** .5]] elif size == 2: # medium mu0 = [4 ** .5, 1.75 ** .5] mutar = [5 ** .5, 1.25 ** .5] murange = [[1 ** .5, 1. ** .5], [7 ** .5, 2.5 ** .5]] elif size == 3: # fat mu0 = [6 ** .5, 4 ** .5] mutar = [2 ** .5, 2.5 ** .5] murange = [[0 ** .5, 2 ** .5], [12 ** .5, 6 ** .5]] elif size == 4: # crowded mu0 = [10 ** .5, 2 ** .5] mutar = [9 ** .5, 2.25 ** .5] murange = [[8 ** .5, 1.5 ** .5], [12 ** .5, 2.5 ** .5]] elif size == 5: # tall mu0 = [11 ** .5, 2.25 ** .5] mutar = [10.5 ** .5, 2.5 ** .5] murange = [[10 ** .5, 1.5 ** .5], [12 ** .5, 3 ** .5]] elif size == 6: # taller mu0 = [11 ** .5, 2.25 ** .5] mutar = [10.5 ** .5, 2.5 ** .5] murange = [[10 ** .5, 1.25 ** .5], [12 ** .5, 3.25 ** .5]] elif size == 7: # low mu0 = [7 ** .5, .75 ** .5] mutar = [6.5 ** .5, .9 ** .5] murange = [[6 ** .5, .5 ** .5], [8 ** .5, 1. ** .5]] aEff = 1.1 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, (aEff*murange[0][1]**2. + bEff*murange[1][1]**2.) ** .5], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, (aEff*murange[1][1]**2. + bEff*murange[0][1]**2.) ** .5]] solver = HSDPE(kappa = 2.5, theta = np.pi / 3, mu0 = mu0, n = 20, verbosity = verb) if ignore_forcing: solver.nbs = 1 -rescaling = [lambda x: np.power(x, 2.), lambda x: x] -rescalingInv = [lambda x: np.power(x, .5), lambda x: x] +rescalingExp = [2., 1.] if algo == "rational": params = {'N':MN, 'M':MN, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R method = RI - elif samples == "pivoted": + elif samples == "pole matching": params['S'] = [SPivot[0]] params['SMarginal'] = [SPivot[1]] params['MMarginal'] = MMarginal params['polybasisPivot'] = "CHEBYSHEV" params['polybasisMarginal'] = "MONOMIAL" params['matchingWeight'] = matchingWeight params['radialBasisMarginal'] = radialM params['radialBasisWeightsMarginal'] = radialWeightM - method = RIPPM + method = RIPM else: #if algo == "RB": params = {'R':R, 'S':S, 'POD':True} - if samples == "distributed": - method = RBD + if samples == "standard": + method = RB elif samples == "centered": params['S'] = R - method = RBD + method = RB + elif samples == "pole matching": + params['S'] = [SPivot[0]] + params['SMarginal'] = [SPivot[1]] + params['MMarginal'] = MMarginal + params['polybasisMarginal'] = "MONOMIAL" + params['matchingWeight'] = matchingWeight + params['radialBasisMarginal'] = radialM + params['radialBasisWeightsMarginal'] = radialWeightM + method = RBPM -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) -elif samples == "pivoted": + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) +elif samples == "pole matching": if sampling == "quadrature": params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "CHEBYSHEV") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "GAUSSLEGENDRE") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "UNIFORM") elif sampling == "quadrature_total": params['samplerPivot'] = QST([murange[0][0], murange[1][0]], "CHEBYSHEV") else: # if sampling == "random": params['samplerPivot'] = RS([murange[0][0], murange[1][0]], "HALTON") if samplingM == "quadrature": params['samplerMarginal'] = QS([murange[0][1], murange[1][1]], "UNIFORM") elif samplingM == "quadrature_total": params['samplerMarginal'] = QST([murange[0][1], murange[1][1]], "CHEBYSHEV") else: # if samplingM == "random": params['samplerMarginal'] = RS([murange[0][1], murange[1][1]], "HALTON") -if samples != "pivoted": +if samples != "pole matching": approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) else: approx = method(solver, mu0 = mu0, directionPivot = [0], approxParameters = params, verbosity = verb) if samples != "centered": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: approx.plotApprox(mutar, name = 'u_app') approx.plotHF(mutar, name = 'u_HF') approx.plotErr(mutar, name = 'err') approx.plotRes(mutar, name = 'res') appErr, solNorm = approx.normErr(mutar), approx.normHF(mutar) resNorm, RHSNorm = approx.normRes(mutar), approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational": from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 1.]) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 20, [2., 1.], clip = clip, relative = False, nobeta = True) diff --git a/examples/2d/pod/square_pod_hermite.py b/examples/2d/pod/square_pod_hermite.py index ae76a86..6a6bd23 100644 --- a/examples/2d/pod/square_pod_hermite.py +++ b/examples/2d/pod/square_pod_hermite.py @@ -1,98 +1,95 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ HelmholtzSquareDomainProblemEngine as HSDPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, RandomSampler as RS, ManualSampler as MS) verb = 0 size = 1 show_sample = False show_norm = True MN = 4 R = (MN + 2) * (MN + 1) // 2 S0 = [3] * 2 S = [25] assert R < np.prod(S) algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "random" if size == 1: # small mu0 = [4 ** .5, 1.5 ** .5] mutar = [5 ** .5, 1.75 ** .5] murange = [[2 ** .5, 1. ** .5], [6 ** .5, 2. ** .5]] elif size == 2: # medium mu0 = [4 ** .5, 1.75 ** .5] mutar = [4.5 ** .5, 1.25 ** .5] murange = [[1 ** .5, 1. ** .5], [7 ** .5, 2.5 ** .5]] elif size == 3: # large mu0 = [6 ** .5, 4 ** .5] mutar = [2 ** .5, 2.5 ** .5] murange = [[0 ** .5, 2 ** .5], [12 ** .5, 6 ** .5]] elif size == 4: # crowded mu0 = [10 ** .5, 2 ** .5] mutar = [9 ** .5, 2.25 ** .5] murange = [[8 ** .5, 1.5 ** .5], [12 ** .5, 2.5 ** .5]] aEff = 1.25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, (aEff*murange[0][1]**2. + bEff*murange[1][1]**2.) ** .5], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, (aEff*murange[1][1]**2. + bEff*murange[0][1]**2.) ** .5]] solver = HSDPE(kappa = 2.5, theta = np.pi / 3, mu0 = mu0, n = 20, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.), lambda x: x] -rescalingInv = [lambda x: np.power(x, .5), lambda x: x] +rescalingExp = [2., 1.] if algo == "rational": params = {'N':MN, 'M':MN, 'S':S, 'POD':True} params['polybasis'] = "CHEBYSHEV" method = RI else: #if algo == "RB": params = {'R':R, 'S':S, 'POD':True} - method = RBD + method = RB if sampling == "quadrature": - sampler0 = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + sampler0 = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) else: # if sampling == "random": - sampler0 = RS(murange, "SOBOL", scaling = rescaling, - scalingInv = rescalingInv) + sampler0 = RS(murange, "SOBOL", scalingExp = rescalingExp) S0 = np.prod(S0) params['sampler'] = MS(murange, points = sampler0.generatePoints(S0)) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) approx.setupApprox() if show_sample: approx.plotApprox(mutar, name = 'u_app') approx.plotHF(mutar, name = 'u_HF') approx.plotErr(mutar, name = 'err') approx.plotRes(mutar, name = 'res') appErr, solNorm = approx.normErr(mutar), approx.normHF(mutar) resNorm, RHSNorm = approx.normRes(mutar), approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational": from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 2.]) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 25, [2., 2.]) diff --git a/examples/2d/pod/square_simplified_pod.py b/examples/2d/pod/square_simplified_pod.py index d01a7e7..8273c12 100644 --- a/examples/2d/pod/square_simplified_pod.py +++ b/examples/2d/pod/square_simplified_pod.py @@ -1,137 +1,127 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ HelmholtzSquareSimplifiedDomainProblemEngine as HSSDPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 5 size = 1 show_sample = False show_norm = True MN = 5 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 samples = "centered" -samples = "distributed" +samples = "standard" algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" sampling = "random" if size == 1: # small mu0 = [4 ** .5, 1.5 ** .5] mutar = [5 ** .5, 1.75 ** .5] murange = [[2 ** .5, 1. ** .5], [6 ** .5, 2. ** .5]] elif size == 2: # medium mu0 = [4 ** .5, 1.75 ** .5] mutar = [5 ** .5, 1.25 ** .5] murange = [[1 ** .5, 1. ** .5], [7 ** .5, 2.5 ** .5]] elif size == 3: # fat mu0 = [6 ** .5, 4 ** .5] mutar = [2 ** .5, 2.5 ** .5] murange = [[0 ** .5, 2 ** .5], [12 ** .5, 6 ** .5]] elif size == 4: # crowded mu0 = [10 ** .5, 2 ** .5] mutar = [9 ** .5, 2.25 ** .5] murange = [[8 ** .5, 1.5 ** .5], [12 ** .5, 2.5 ** .5]] elif size == 5: # tall mu0 = [11 ** .5, 2.25 ** .5] mutar = [10.5 ** .5, 2.5 ** .5] murange = [[10 ** .5, 1.5 ** .5], [12 ** .5, 3 ** .5]] elif size == 6: # taller mu0 = [11 ** .5, 2.25 ** .5] mutar = [10.5 ** .5, 2.5 ** .5] murange = [[10 ** .5, 1.25 ** .5], [12 ** .5, 3.25 ** .5]] elif size == 7: # low mu0 = [7 ** .5, .75 ** .5] mutar = [8 ** .5, 1 ** .5] murange = [[6 ** .5, .25 ** .5], [8 ** .5, 1.25 ** .5]] aEff = 1.25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, (aEff*murange[0][1]**2. + bEff*murange[1][1]**2.) ** .5], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, (aEff*murange[1][1]**2. + bEff*murange[0][1]**2.) ** .5]] solver = HSSDPE(kappa = 2.5, theta = np.pi / 3, mu0 = mu0, n = 20, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.)] * 2 -rescalingInv = [lambda x: np.power(x, .5)] * 2 +rescalingExp = [2.] * 2 if algo == "rational": params = {'N':MN, 'M':MN, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" params['polybasis'] = "LEGENDRE" params['polybasis'] = "MONOMIAL" params['E'] = MN - method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R - method = RI + method = RI else: #if algo == "RB": params = {'R':R, 'S':S, 'POD':True} - if samples == "distributed": - method = RBD - elif samples == "centered": + if samples == "centered": params['S'] = R - method = RBD + method = RB -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) approx.setupApprox() if show_sample: approx.plotApprox(mutar, name = 'u_app') approx.plotHF(mutar, name = 'u_HF') approx.plotErr(mutar, name = 'err') approx.plotRes(mutar, name = 'res') appErr, solNorm = approx.normErr(mutar), approx.normHF(mutar) resNorm, RHSNorm = approx.normRes(mutar), approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational": from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 2.]) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 25, [2., 2.]) diff --git a/examples/2d/pod/square_simplified_pod_hermite.py b/examples/2d/pod/square_simplified_pod_hermite.py index 1d0bb44..3257756 100644 --- a/examples/2d/pod/square_simplified_pod_hermite.py +++ b/examples/2d/pod/square_simplified_pod_hermite.py @@ -1,98 +1,95 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ HelmholtzSquareSimplifiedDomainProblemEngine as HSSDPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, RandomSampler as RS, ManualSampler as MS) verb = 0 size = 1 show_sample = False show_norm = True MN = 4 R = (MN + 2) * (MN + 1) // 2 S0 = [3] * 2 S = [25] assert R < np.prod(S) algo = "rational" #algo = "RB" sampling = "quadrature" #sampling = "random" if size == 1: # small mu0 = [4 ** .5, 1.5 ** .5] mutar = [5 ** .5, 1.75 ** .5] murange = [[2 ** .5, 1. ** .5], [6 ** .5, 2. ** .5]] elif size == 2: # medium mu0 = [4 ** .5, 1.75 ** .5] mutar = [4.5 ** .5, 1.25 ** .5] murange = [[1 ** .5, 1. ** .5], [7 ** .5, 2.5 ** .5]] elif size == 3: # large mu0 = [6 ** .5, 4 ** .5] mutar = [2 ** .5, 2.5 ** .5] murange = [[0 ** .5, 2 ** .5], [12 ** .5, 6 ** .5]] elif size == 4: # crowded mu0 = [10 ** .5, 2 ** .5] mutar = [9 ** .5, 2.25 ** .5] murange = [[8 ** .5, 1.5 ** .5], [12 ** .5, 2.5 ** .5]] aEff = 1.25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, (aEff*murange[0][1]**2. + bEff*murange[1][1]**2.) ** .5], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, (aEff*murange[1][1]**2. + bEff*murange[0][1]**2.) ** .5]] solver = HSSDPE(kappa = 2.5, theta = np.pi / 3, mu0 = mu0, n = 20, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.)] * 2 -rescalingInv = [lambda x: np.power(x, .5)] * 2 +rescalingExp = [2.] * 2 if algo == "rational": params = {'N':MN, 'M':MN, 'S':S, 'POD':True} params['polybasis'] = "CHEBYSHEV" method = RI else: #if algo == "RB": params = {'R':R, 'S':S, 'POD':True} - method = RBD + method = RB if sampling == "quadrature": - sampler0 = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + sampler0 = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) else: # if sampling == "random": - sampler0 = RS(murange, "SOBOL", scaling = rescaling, - scalingInv = rescalingInv) + sampler0 = RS(murange, "SOBOL", scalingExp = rescalingExp) S0 = np.prod(S0) params['sampler'] = MS(murange, points = sampler0.generatePoints(S0)) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) approx.setupApprox() if show_sample: approx.plotApprox(mutar, name = 'u_app') approx.plotHF(mutar, name = 'u_HF') approx.plotErr(mutar, name = 'err') approx.plotRes(mutar, name = 'res') appErr, solNorm = approx.normErr(mutar), approx.normHF(mutar) resNorm, RHSNorm = approx.normRes(mutar), approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational": from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 2.]) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 50, [2., 2.]) diff --git a/examples/2d/pod/synthetic_pod.py b/examples/2d/pod/synthetic_pod.py index 4749aca..b91fc84 100644 --- a/examples/2d/pod/synthetic_pod.py +++ b/examples/2d/pod/synthetic_pod.py @@ -1,149 +1,140 @@ import numpy as np from rrompy.hfengines.linear_problem.bidimensional import \ SyntheticBivariateEngine as SBE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 5 size = 1 show_sample = True show_norm = True clip = -1 #clip = .4 #clip = .6 Delta = 0 MN = 10 R = (MN + 2) * (MN + 1) // 2 S = [int(np.ceil(R ** .5))] * 2 PODTol = 1e-6 samples = "centered" -samples = "distributed" +samples = "standard" algo = "rational" #algo = "RB" sampling = "quadrature" #sampling = "quadrature_total" #sampling = "random" -if samples == "distributed": +if samples == "standard": radial = 0 radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 10. radialWeight = [rW0] * 2 if size == 1: # small mu0 = [10. ** .5, 15. ** .5] mutar = [12. ** .5, 14. ** .5] murange = [[5. ** .5, 10. ** .5], [15 ** .5, 20 ** .5]] if size == 2: # large mu0 = [15. ** .5, 17.5 ** .5] mutar = [18. ** .5, 22. ** .5] murange = [[5. ** .5, 10. ** .5], [25 ** .5, 25 ** .5]] if size == 3: # medium mu0 = [17.5 ** .5, 15 ** .5] mutar = [20. ** .5, 18. ** .5] murange = [[10. ** .5, 10. ** .5], [25 ** .5, 20 ** .5]] assert Delta <= 0 aEff = 1.#25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, aEff*murange[0][1] + bEff*murange[1][1]], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, aEff*murange[1][1] + bEff*murange[0][1]]] kappa = 20. ** .5 theta = - np.pi / 6. n = 20 L = np.pi solver = SBE(kappa = kappa, theta = theta, n = n, L = L, mu0 = mu0, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.)] * 2 -rescalingInv = [lambda x: np.power(x, .5)] * 2 +rescalingExp = [2.] * 2 if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R method = RI else: #if algo == "RB": params = {'R':(MN + 2 + Delta) * (MN + 1 + Delta) // 2, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD - elif samples == "centered": + if samples == "centered": params['S'] = R - method = RBD + method = RB -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) -if samples == "distributed": approx.samplingEngine.allowRepeatedSamples = False +if samples == "standard": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: L = mutar[1] approx.plotApprox(mutar, name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, name = 'res', homogeneized = False, what = "REAL") appErr = approx.normErr(mutar) solNorm = approx.normHF(mutar) resNorm = approx.normRes(mutar) RHSNorm = approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if algo == "rational" and approx.N > 0: from plot_zero_set import plotZeroSet2 muZeroVals, Qvals = plotZeroSet2(murange, murangeEff, approx, mu0, 200, [2., 2.], clip = clip) if show_norm: solver._solveBatchSize = 100 from plot_inf_set import plotInfSet2 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet2( murange, murangeEff, approx, mu0, 50, [2., 2.], clip = clip, relative = False) diff --git a/examples/3d/base/matrix_3.py b/examples/3d/base/matrix_3.py new file mode 100644 index 0000000..dce8d7b --- /dev/null +++ b/examples/3d/base/matrix_3.py @@ -0,0 +1,74 @@ +import scipy.sparse as sp +import numpy as np +from rrompy.hfengines.base import MatrixEngineBase as MEB + +verb = 100 + +deg = 2 + +N = 150 +exp = 1.05 +assert exp > 1. +empty = sp.csr_matrix((np.zeros(0), np.zeros(0), np.zeros(N + 1)), + shape = (N, N)) +solver = MEB(verbosity = verb) +solver.npar = 3 +A0 = sp.spdiags([np.arange(1, 1 + 2 * N, 2) ** exp - (2 * (N // 4)) ** exp], + [0], N, N) +if deg == 1: + solver.nAs = 4 + solver.As = [A0, sp.eye(N), - sp.eye(N), - sp.eye(N)] +elif deg == 2: + solver.nAs = 7 + solver.As = ([A0] + [empty] + [- sp.eye(N)] + [empty] * 3 + [sp.eye(N)]) +elif deg == 3: + solver.nAs = 13 + solver.As = ([A0] + [empty] + [- sp.eye(N)] + [empty] * 9 + [sp.eye(N)]) +np.random.seed(420) +solver.nbs = 1 +solver.bs = [np.random.randn(N) + 1.j * np.random.randn(N)] + +mu0 = [.8, 0., .2] + +uh = solver.solve(mu0)[0] +solver.plot(uh, what = 'REAL', figsize = (8, 5)) + + + +murange = np.linspace(-1., 1., 20) +Mu1, Mu2, Mu3 = np.meshgrid(murange, murange, murange, indexing = 'ij') +mus = [] +if deg == 1: + f = Mu1 - Mu2 - Mu3 +elif deg == 2: + f = Mu1 * Mu3 - Mu2 +elif deg == 3: + f = Mu3 * Mu1**2 - Mu2 + +from matplotlib import pyplot as plt +pts = [] +for jdir in range(len(Mu3)): + z = Mu3[0, 0, jdir] + xis, yis, fis = Mu1[:, :, jdir], Mu2[:, :, jdir], f[:, :, jdir] + plt.figure() + CS = plt.contour(xis, yis, np.real(fis), levels = [0.]) + plt.close() + for i, CSc in enumerate(CS.allsegs): + if np.isclose(CS.cvalues[i], 0.): + for j, CScj in enumerate(CSc): + for k in range(len(CScj)): + pts += [[CScj[k, 0], CScj[k, 1], z]] + pts += [[np.nan] * 3] +pts = np.array(pts) +from mpl_toolkits.mplot3d import Axes3D +fig = plt.figure(figsize = (8, 6)) +ax = Axes3D(fig) +ax.plot(pts[:, 0], pts[:, 1], pts[:, 2], 'k-') +ax.set_xlim(-1., 1.) +ax.set_ylim(-1., 1.) +ax.set_zlim(-1., 1.) +ax.set_xlabel('x') +ax.set_ylabel('y') +ax.set_zlabel('z') +plt.show() +plt.close() diff --git a/examples/3d/pod/fracture3_pod.py b/examples/3d/pod/fracture3_pod.py index cba9424..802dca1 100644 --- a/examples/3d/pod/fracture3_pod.py +++ b/examples/3d/pod/fracture3_pod.py @@ -1,260 +1,253 @@ import numpy as np from mpl_toolkits.mplot3d import Axes3D from matplotlib import pyplot as plt from rrompy.hfengines.linear_problem.tridimensional import \ MembraneFractureEngine3 as MFE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD -from rrompy.reduction_methods.pivoting import \ - RationalInterpolantPivotedPoleMatching as RIPPM -from rrompy.reduction_methods.pivoting import \ - RBDistributedPivotedPoleMatching as RBP +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.reduction_methods.pole_matching import \ + RationalInterpolantPoleMatching as RIPM +from rrompy.reduction_methods.pole_matching import \ + ReducedBasisPoleMatching as RBPM from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 70 size = 4 show_sample = False show_norm = False clip = -1 #clip = .4 #clip = .6 Delta = 0 MN = 5 R = (MN + 3) * (MN + 2) * (MN + 1) // 6 S = [int(np.ceil(R ** (1. / 3.)))] * 3 PODTol = 1e-8 SPivot = [MN + 1, 2, 2] MMarginal = SPivot[1] - 1 matchingWeight = 10. samples = "centered" -samples = "distributed" -samples = "pivoted" +samples = "standard" +samples = "pole matching" algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" #sampling = "random" samplingM = "quadrature" #samplingM = "quadrature_total" #samplingM = "random" -if samples == "distributed": +if samples == "standard": radial = 0 radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 5. radialWeight = [rW0] * 3 -if samples == "pivoted": +if samples == "pole matching": radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 5. radialWeight = [rW0] radialM = 0 radialM = "gaussian" # radialM = "thinplate" # radialM = "multiquadric" rMW0 = 2. radialWeightM = [rMW0] * 2 assert Delta <= 0 if size == 1: mu0 = [47.5 ** .5, .4, .05] mutar = [50 ** .5, .45, .07] murange = [[40 ** .5, .3, .025], [55 ** .5, .5, .075]] if size == 2: mu0 = [50 ** .5, .3, .02] mutar = [55 ** .5, .4, .03] murange = [[40 ** .5, .1, .005], [60 ** .5, .5, .035]] if size == 3: mu0 = [45 ** .5, .5, .05] mutar = [47 ** .5, .4, .045] murange = [[40 ** .5, .3, .04], [50 ** .5, .7, .06]] if size == 4: mu0 = [45 ** .5, .4, .05] mutar = [47 ** .5, .45, .045] murange = [[40 ** .5, .3, .04], [50 ** .5, .5, .06]] aEff = 1.#25 bEff = 1. - aEff murangeEff = [[(aEff*murange[0][0]**2. + bEff*murange[1][0]**2.) ** .5, aEff*murange[0][1] + bEff*murange[1][1], aEff*murange[0][2] + bEff*murange[1][2]], [(aEff*murange[1][0]**2. + bEff*murange[0][0]**2.) ** .5, aEff*murange[1][1] + bEff*murange[0][1], aEff*murange[1][2] + bEff*murange[0][2]]] H = 1. L = .75 delta = .05 n = 50 solver = MFE(mu0 = mu0, H = H, L = L, delta = delta, n = n, verbosity = verb) -rescaling = [lambda x: np.power(x, 2.), lambda x: x, lambda x: x] -rescalingInv = [lambda x: np.power(x, .5), lambda x: x, lambda x: x] +rescalingExp = [2., 1., 1.] if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R method = RI - elif samples == "pivoted": + elif samples == "pole matching": params['S'] = [SPivot[0]] params['SMarginal'] = SPivot[1:] params['MMarginal'] = MMarginal params['polybasisPivot'] = "CHEBYSHEV" params['polybasisMarginal'] = "MONOMIAL" params['matchingWeight'] = matchingWeight params['radialBasisPivot'] = radial params['radialBasisMarginal'] = radialM params['radialBasisWeightsPivot'] = radialWeight params['radialBasisWeightsMarginal'] = radialWeightM - method = RIPPM + method = RIPM else: #if algo == "RB": params = {'R':(MN + 3 + Delta) * (MN + 2 + Delta) * (MN + 1 + Delta) // 6, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD + if samples == "standard": + method = RB elif samples == "centered": params['S'] = R - method = RBD - elif samples == "pivoted": + method = RB + elif samples == "pole matching": params['S'] = [SPivot[0]] params['SMarginal'] = SPivot[1:] params['MMarginal'] = MMarginal params['polybasisMarginal'] = "MONOMIAL" params['matchingWeight'] = matchingWeight params['radialBasisMarginal'] = radialM params['radialBasisWeightsMarginal'] = radialWeightM - method = RBP + method = RBPM -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV", scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "GAUSSLEGENDRE",scalingExp = rescalingExp) +# params['sampler'] = QS(murange, "UNIFORM", scalingExp = rescalingExp) params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV", scalingExp = rescalingExp) params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON", scalingExp = rescalingExp) params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) -elif samples == "pivoted": + params['sampler'] = MS(murange, points = [mu0], scalingExp = rescalingExp) +elif samples == "pole matching": if sampling == "quadrature": params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "CHEBYSHEV") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "GAUSSLEGENDRE") # params['samplerPivot'] = QS([murange[0][0], murange[1][0]], "UNIFORM") elif sampling == "quadrature_total": params['samplerPivot'] = QST([murange[0][0], murange[1][0]], "CHEBYSHEV") params['S'] = MN + 1 else: # if sampling == "random": params['samplerPivot'] = RS([murange[0][0], murange[1][0]], "HALTON") params['S'] = MN + 1 if samplingM == "quadrature": params['samplerMarginal'] = QS([murange[0][1:], murange[1][1:]], "UNIFORM") elif samplingM == "quadrature_total": params['samplerMarginal'] = QST([murange[0][1:], murange[1][1:]], "CHEBYSHEV") params['SMarginal'] = (MMarginal + 2) * (MMarginal + 1) // 2 params['polybasisMarginal'] = "CHEBYSHEV" else: # if samplingM == "random": params['samplerMarginal'] = RS([murange[0][1:], murange[1][1:]], "HALTON") params['SMarginal'] = (MMarginal + 2) * (MMarginal + 1) // 2 -if samples != "pivoted": +if samples != "pole matching": approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) else: approx = method(solver, mu0 = mu0, directionPivot = [0], approxParameters = params, verbosity = verb) if samples != "centered": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: from fracture3_warping import fracture3_warping warps = fracture3_warping(solver.V.mesh(), L, mutar[1], delta, mutar[2]) approx.plotApprox(mutar, warps, name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, warps, name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, warps, name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, warps, name = 'res', # homogeneized = False, what = "REAL") appErr = approx.normErr(mutar) solNorm = approx.normHF(mutar) resNorm = approx.normRes(mutar) RHSNorm = approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) fig = plt.figure(figsize = (8, 6)) ax = Axes3D(fig) ax.scatter(np.real(approx.mus(0) ** 2.), np.real(approx.mus(1)), np.real(approx.mus(2)), '.') plt.show() plt.close() approx.verbosity = 0 approx.trainedModel.verbosity = 0 from plot_zero_set_3 import plotZeroSet3 #muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, # [None, mu0[1], mu0[2]], [2., 1., 1.], # clip = clip) #muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, # [None, None, mu0[2]], [2., 1., 1.], # clip = clip) #muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, # [None, mu0[1], None], [2., 1., 1.], # clip = clip) muZeroScatter = plotZeroSet3(murange, murangeEff, approx, mu0, 50, [None, None, None], [2., 1., 1.], clip = clip) if show_norm: solver._solveBatchSize = 25 from plot_inf_set_3 import plotInfSet3 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, mu0[1], mu0[2]], [2., 1., 1.], clip = clip, relative = False, normalizeDen = True) muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, None, mu0[2]], [2., 1., 1.], clip = clip, relative = False, normalizeDen = True) muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, mu0[1], None], [2., 1., 1.], clip = clip, relative = False, normalizeDen = True) print(approx.getPoles([None, .5, .05]) ** 2.) diff --git a/examples/3d/pod/matrix_3_pod.py b/examples/3d/pod/matrix_3_pod.py new file mode 100644 index 0000000..ae358a5 --- /dev/null +++ b/examples/3d/pod/matrix_3_pod.py @@ -0,0 +1,187 @@ +import numpy as np +import scipy.sparse as sp +from mpl_toolkits.mplot3d import Axes3D +from matplotlib import pyplot as plt +from rrompy.hfengines.base import MatrixEngineBase as MEB +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, + QuadratureSamplerTotal as QST, + ManualSampler as MS, + RandomSampler as RS) + +verb = 50 +deg = 2 +size = 1 +show_sample = True +show_norm = False + +Delta = 0 +MN = 15 +R = (MN + 3) * (MN + 2) * (MN + 1) // 6 +S = [int(np.ceil(R ** (1. / 3.)))] * 3 +PODTol = 1e-8 + +samples = "centered" +samples = "standard" +#samples, nDer = "standard_MMM", 2 +algo = "rational" +#algo = "RB" +sampling = "quadrature" +sampling = "quadrature_total" +sampling = "random" + +if samples == "standard": + radial = 0 +# radial = "gaussian" +# radial = "thinplate" +# radial = "multiquadric" + rW0 = 5. + radialWeight = [rW0] * 2 + +assert Delta <= 0 + +if size == 1: + mu0 = [0.] * 3 + mutar = [.8, .8, .8] + murange = [[-1.] * 3, [1.] * 3] + +aEff = 1.#25 +bEff = 1. - aEff +murangeEff = [[aEff*murange[0][0] + bEff*murange[1][0], + aEff*murange[0][1] + bEff*murange[1][1], + aEff*murange[0][2] + bEff*murange[1][2]], + [aEff*murange[1][0] + bEff*murange[0][0], + aEff*murange[1][1] + bEff*murange[0][1], + aEff*murange[1][2] + bEff*murange[0][2]]] + +N = 150 +exp = 1.05 +assert exp > 1. +empty = sp.csr_matrix((np.zeros(0), np.zeros(0), np.zeros(N + 1)), + shape = (N, N)) +solver = MEB(verbosity = verb) +solver.npar = 3 +A0 = sp.spdiags([np.arange(1, 1 + 2 * N, 2) ** exp - (2 * (N // 4)) ** exp], + [0], N, N) +if deg == 1: + solver.nAs = 4 + solver.As = [A0, sp.eye(N), - sp.eye(N), - sp.eye(N)] +elif deg == 2: + solver.nAs = 7 + solver.As = [A0] + [empty] + [- sp.eye(N)] + [empty] * 3 + [sp.eye(N)] +elif deg == 3: + solver.nAs = 13 + solver.As = [A0] + [empty] + [- sp.eye(N)] + [empty] * 9 + [sp.eye(N)] +np.random.seed(420) +solver.nbs = 1 +solver.bs = [np.random.randn(N) + 1.j * np.random.randn(N)] + + +if algo == "rational": + params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} + if samples == "standard": + params['polybasis'] = "CHEBYSHEV" +# params['polybasis'] = "LEGENDRE" +# params['polybasis'] = "MONOMIAL" + params['E'] = MN + params['radialBasis'] = radial + params['radialBasisWeights'] = radialWeight + elif samples == "centered": + params['polybasis'] = "MONOMIAL" + params['S'] = R + else: #MMM + params['S'] = nDer * int(np.ceil(R / nDer)) + method = RI +else: #if algo == "RB": + params = {'R':(MN + 3 + Delta) * (MN + 2 + Delta) * (MN + 1 + Delta) // 6, + 'S':S, 'POD':True, 'PODTolerance':PODTol} + if samples == "standard": + pass + elif samples == "centered": + params['S'] = R + else: #MMM + params['S'] = nDer * int(np.ceil(R / nDer)) + method = RB + +if samples == "standard": + if sampling == "quadrature": + params['sampler'] = QS(murange, "CHEBYSHEV") +# params['sampler'] = QS(murange, "GAUSSLEGENDRE") +# params['sampler'] = QS(murange, "UNIFORM") + params['S'] = [max(j, MN + 1) for j in params['S']] + elif sampling == "quadrature_total": + params['sampler'] = QST(murange, "CHEBYSHEV") + params['S'] = R + else: # if sampling == "random": + params['sampler'] = RS(murange, "HALTON") + params['S'] = R +elif samples == "centered": + params['sampler'] = MS(murange, points = [mu0]) +elif samples == "standard_MMM": + if sampling == "quadrature": + SdirEff = int(np.ceil(int(np.ceil(R / nDer)) ** (1. / 3))) + pts = QS(murange, "CHEBYSHEV").generatePoints([SdirEff] * 3) + elif sampling == "quadrature_total": + pts = QST(murange, "CHEBYSHEV").generatePoints(int(np.ceil(R / nDer))) + else: # if sampling == "random": + pts = RS(murange, "HALTON").generatePoints(int(np.ceil(R / nDer))) + params['sampler'] = MS(murange, points = pts) + +approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb) +if samples == "standard": approx.samplingEngine.allowRepeatedSamples = False + +approx.setupApprox() +if show_sample: + approx.plotApprox(mutar, name = 'u_app', what = "REAL") + approx.plotHF(mutar, name = 'u_HF', what = "REAL") + approx.plotErr(mutar, name = 'err', what = "REAL") +# approx.plotRes(mutar, name = 'res', what = "REAL") + appErr = approx.normErr(mutar) + solNorm = approx.normHF(mutar) + resNorm = approx.normRes(mutar) + RHSNorm = approx.normRHS(mutar) + print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, + np.divide(appErr, solNorm))) + print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, + np.divide(resNorm, RHSNorm))) + +fig = plt.figure(figsize = (8, 6)) +ax = Axes3D(fig) +ax.scatter(approx.trainedModel.data.mus(0), approx.trainedModel.data.mus(1), + approx.trainedModel.data.mus(2), '.') +ax.set_xlim3d(murangeEff[0][0], murangeEff[1][0]) +ax.set_ylim3d(murangeEff[0][1], murangeEff[1][1]) +ax.set_zlim3d(murangeEff[0][2], murangeEff[1][2]) +plt.show() +plt.close() + +approx.verbosity = 0 +approx.trainedModel.verbosity = 0 +if algo == "rational" and approx.N > 0: + from plot_zero_set_3 import plotZeroSet3 +# muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, +# [None, mu0[1], mu0[2]], [1., 1., 1.]) +# muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, +# [None, None, mu0[2]], [1., 1., 1.]) +# muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, +# [None, mu0[1], None], [1., 1., 1.]) + plotZeroSet3(murange, murangeEff, approx, mu0, 25, [None, None, None], + [1., 1., 1.], imagTol = 1e-2) + +if show_norm: + solver._solveBatchSize = 25 + from plot_inf_set_3 import plotInfSet3 + muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( + murange, murangeEff, approx, mu0, 25, + [None, mu0[1], mu0[2]], [1., 1., 1.], + relative = False, normalizeDen = True) + muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( + murange, murangeEff, approx, mu0, 25, + [None, None, mu0[2]], [1., 1., 1.], + relative = False, normalizeDen = True) + muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( + murange, murangeEff, approx, mu0, 25, + [None, mu0[1], None], [1., 1., 1.], + relative = False, normalizeDen = True) + diff --git a/examples/3d/pod/scattering1_pod.py b/examples/3d/pod/scattering1_pod.py index 52d0705..7ac695f 100644 --- a/examples/3d/pod/scattering1_pod.py +++ b/examples/3d/pod/scattering1_pod.py @@ -1,207 +1,190 @@ import numpy as np from mpl_toolkits.mplot3d import Axes3D from matplotlib import pyplot as plt from rrompy.hfengines.linear_problem.tridimensional import Scattering1d as S1D -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, QuadratureSamplerTotal as QST, ManualSampler as MS, RandomSampler as RS) verb = 50 size = 2 show_sample = True show_norm = False clip = -1 #clip = .4 #clip = .6 homogeneize = False #homogeneize = True Delta = 0 MN = 15 R = (MN + 3) * (MN + 2) * (MN + 1) // 6 S = [int(np.ceil(R ** (1. / 3.)))] * 3 PODTol = 1e-8 samples = "centered" -samples = "distributed" -samples, nDer = "distributed_MMM", 15 +samples = "standard" +samples, nDer = "standard_MMM", 15 algo = "rational" #algo = "RB" sampling = "quadrature" sampling = "quadrature_total" sampling = "random" -if samples == "distributed": +if samples == "standard": radial = 0 # radial = "gaussian" # radial = "thinplate" # radial = "multiquadric" rW0 = 5. radialWeight = [rW0] * 2 assert Delta <= 0 if size == 1: mu0 = [4., np.pi, 0.] mutar = [4.05, .95 * np.pi, .2] murange = [[2., .9 * np.pi, -.5], [6., 1.1 * np.pi, .5]] if size == 2: mu0 = [4., np.pi, .375] mutar = [4.05, .95 * np.pi, .2] murange = [[2., .9 * np.pi, 0.], [6., 1.1 * np.pi, .75]] aEff = 1.#25 bEff = 1. - aEff murangeEff = [[aEff*murange[0][0] + bEff*murange[1][0], aEff*murange[0][1] + bEff*murange[1][1], aEff*murange[0][2] + bEff*murange[1][2]], [aEff*murange[1][0] + bEff*murange[0][0], aEff*murange[1][1] + bEff*murange[0][1], aEff*murange[1][2] + bEff*murange[0][2]]] n = 100 solver = S1D(mu0 = mu0, n = n, verbosity = verb) -rescaling = [lambda x: x, lambda x: x, lambda x: x] -rescalingInv = [lambda x: x, lambda x: x, lambda x: x] if algo == "rational": params = {'N':MN, 'M':MN + Delta, 'S':S, 'POD':True} - if samples == "distributed": + if samples == "standard": params['polybasis'] = "CHEBYSHEV" # params['polybasis'] = "LEGENDRE" # params['polybasis'] = "MONOMIAL" params['E'] = MN params['radialBasis'] = radial params['radialBasisWeights'] = radialWeight - method = RI elif samples == "centered": params['polybasis'] = "MONOMIAL" params['S'] = R - method = RI else: #MMM params['S'] = nDer * int(np.ceil(R / nDer)) - method = RI + method = RI else: #if algo == "RB": params = {'R':(MN + 3 + Delta) * (MN + 2 + Delta) * (MN + 1 + Delta) // 6, 'S':S, 'POD':True, 'PODTolerance':PODTol} - if samples == "distributed": - method = RBD + if samples == "standard": + pass elif samples == "centered": params['S'] = R - method = RBD else: #MMM params['S'] = nDer * int(np.ceil(R / nDer)) - method = RBD + method = RB -if samples == "distributed": +if samples == "standard": if sampling == "quadrature": - params['sampler'] = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "GAUSSLEGENDRE", scaling = rescaling, -# scalingInv = rescalingInv) -# params['sampler'] = QS(murange, "UNIFORM", scaling = rescaling, -# scalingInv = rescalingInv) + params['sampler'] = QS(murange, "CHEBYSHEV") +# params['sampler'] = QS(murange, "GAUSSLEGENDRE") +# params['sampler'] = QS(murange, "UNIFORM") params['S'] = [max(j, MN + 1) for j in params['S']] elif sampling == "quadrature_total": - params['sampler'] = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = QST(murange, "CHEBYSHEV") params['S'] = R else: # if sampling == "random": - params['sampler'] = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv) + params['sampler'] = RS(murange, "HALTON") params['S'] = R elif samples == "centered": - params['sampler'] = MS(murange, points = [mu0], scaling = rescaling, - scalingInv = rescalingInv) -elif samples == "distributed_MMM": + params['sampler'] = MS(murange, points = [mu0]) +elif samples == "standard_MMM": if sampling == "quadrature": SdirEff = int(np.ceil(int(np.ceil(R / nDer)) ** (1. / 3))) - pts = QS(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv).generatePoints([SdirEff] * 3) + pts = QS(murange, "CHEBYSHEV").generatePoints([SdirEff] * 3) elif sampling == "quadrature_total": - pts = QST(murange, "CHEBYSHEV", scaling = rescaling, - scalingInv = rescalingInv).generatePoints( - int(np.ceil(R / nDer))) + pts = QST(murange, "CHEBYSHEV").generatePoints(int(np.ceil(R / nDer))) else: # if sampling == "random": - pts = RS(murange, "HALTON", scaling = rescaling, - scalingInv = rescalingInv).generatePoints( - int(np.ceil(R / nDer))) - params['sampler'] = MS(murange, points = pts, scaling = rescaling, - scalingInv = rescalingInv) + pts = RS(murange, "HALTON").generatePoints(int(np.ceil(R / nDer))) + params['sampler'] = MS(murange, points = pts) approx = method(solver, mu0 = mu0, approxParameters = params, verbosity = verb, homogeneized = homogeneize) -if samples == "distributed": approx.samplingEngine.allowRepeatedSamples = False +if samples == "standard": approx.samplingEngine.allowRepeatedSamples = False approx.setupApprox() if show_sample: import fenics as fen x = fen.SpatialCoordinate(solver.V.mesh()) warps = [x * mutar[1] / solver._L - x, x * solver._L / mutar[1] - x] approx.plotApprox(mutar, warps, name = 'u_app', homogeneized = False, what = "REAL") approx.plotHF(mutar, warps, name = 'u_HF', homogeneized = False, what = "REAL") approx.plotErr(mutar, warps, name = 'err', homogeneized = False, what = "REAL") # approx.plotRes(mutar, warps, name = 'res', # homogeneized = False, what = "REAL") appErr = approx.normErr(mutar, homogeneized = homogeneize) solNorm = approx.normHF(mutar, homogeneized = homogeneize) resNorm = approx.normRes(mutar, homogeneized = homogeneize) RHSNorm = approx.normRHS(mutar, homogeneized = homogeneize) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) fig = plt.figure(figsize = (8, 6)) ax = Axes3D(fig) ax.scatter(approx.trainedModel.data.mus(0), approx.trainedModel.data.mus(1), approx.trainedModel.data.mus(2), '.') ax.set_xlim3d(murangeEff[0][0], murangeEff[1][0]) ax.set_ylim3d(murangeEff[0][1], murangeEff[1][1]) ax.set_zlim3d(murangeEff[0][2], murangeEff[1][2]) plt.show() plt.close() approx.verbosity = 0 approx.trainedModel.verbosity = 0 if algo == "rational" and approx.N > 0: from plot_zero_set_3 import plotZeroSet3 muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, [None, mu0[1], mu0[2]], [1., 1., 1.], clip = clip) muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, [None, None, mu0[2]], [1., 1., 1.], clip = clip) muZeroVals, Qvals = plotZeroSet3(murange, murangeEff, approx, mu0, 200, [None, mu0[1], None], [1., 1., 1.], clip = clip) plotZeroSet3(murange, murangeEff, approx, mu0, 100, [None, None, None], [1., 1., 1.], clip = clip, imagTol = 1e-2) if show_norm: solver._solveBatchSize = 25 from plot_inf_set_3 import plotInfSet3 muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, mu0[1], mu0[2]], [1., 1., 1.], clip = clip, relative = False, normalizeDen = True) muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, None, mu0[2]], [1., 1., 1.], clip = clip, relative = False, normalizeDen = True) muInfVals, normEx, normApp, normRes, normErr, beta = plotInfSet3( murange, murangeEff, approx, mu0, 25, [None, mu0[1], None], [1., 1., 1.], clip = clip, relative = False, normalizeDen = True) print(approx.getPoles([None, np.pi, 0.])) diff --git a/examples/airfoil/greedy.py b/examples/airfoil/greedy.py index 373d19c..1f23b37 100644 --- a/examples/airfoil/greedy.py +++ b/examples/airfoil/greedy.py @@ -1,106 +1,109 @@ import numpy as np from airfoil_engine import AirfoilScatteringEngine -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RI +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RB from rrompy.solver.fenics import L2NormMatrix +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS -verb = 2 +verb = 5 timed = False -algo = "Pade" +algo = "RI" #algo = "RB" polyBasis = "LEGENDRE" #polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" homog = True homog = False -k0s = np.linspace(5, 20, 100) +k0s = np.linspace(5, 10, 100) k0 = np.mean(k0s) kl, kr = min(k0s), max(k0s) -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':2, 'basis':polyBasis} +params = {'S':5, 'sampler':QS([kl, kr], "UNIFORM"), 'nTestPoints':500, + 'greedyTol':1e-2, 'polybasis':polyBasis, + 'errorEstimatorKind':'BASIC'} ######### kappa = 10 theta = np.pi * - 45 / 180. solver = AirfoilScatteringEngine(kappa, theta, verbosity = verb, degree_threshold = 8) ######### -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb, homogeneized = homog) +if algo == "RI": + approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, + homogeneized = homog) else: + params.pop("polybasis") + params.pop("errorEstimatorKind") approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) if timed: from time import clock start_time = clock() approx.greedy() print("Time: ", clock() - start_time) else: approx.greedy(True) approx.samplingEngine.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) res = np.zeros_like(normApp) err = np.zeros_like(normApp) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) res[j] = (approx.estimatorNormEngine.norm( - approx.getRes(k0s[j], homogeneized=homog)) + approx.getRes(k0s[j], homogeneized = homog, duality = False)) / approx.estimatorNormEngine.norm( - approx.getRHS(k0s[j], homogeneized=homog))) + approx.getRHS(k0s[j], homogeneized = homog, duality = False))) err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) resApp = approx.errorEstimator(k0s) plt.figure() plt.plot(k0s, norm) plt.plot(k0s, normApp, '--') -plt.plot(np.real(approx.mus), - 1.05*np.max(norm)*np.ones_like(approx.mus, dtype = float), 'rx') +plt.plot(np.real(approx.mus.data), + 1.05*np.max(norm)*np.ones_like(approx.mus.data, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, res) plt.semilogy(k0s, resApp, '--') -plt.semilogy(np.real(approx.mus), - 4.*np.max(resApp)*np.ones_like(approx.mus, dtype = float), 'rx') +plt.semilogy(np.real(approx.mus.data), + 4.*np.max(resApp)*np.ones_like(approx.mus.data, dtype = float), + 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() polesApp = approx.getPoles() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/airfoil/pod.py b/examples/airfoil/pod.py index 099ee00..c51576b 100644 --- a/examples/airfoil/pod.py +++ b/examples/airfoil/pod.py @@ -1,110 +1,108 @@ import numpy as np from airfoil_engine import AirfoilScatteringEngine -from rrompy.reduction_methods.distributed import RationalInterpolant as Pade -from rrompy.reduction_methods.distributed import RBDistributed as RB +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS verb = 100 homog = True homog = False sol = "single" sol = "sweep" -algo = "Pade" +algo = "RI" algo = "RB" polyBasis = "LEGENDRE" polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" Nsweep = 100 k0s = [x * 2 * np.pi / 340 for x in [1.0e2, 5.0e2]] k0 = np.mean(np.power(k0s, 2.)) ** .5 ktar = k0s[0] + (k0s[1] - k0s[0]) * .7 params = {'N':29, 'M':29, 'R':30, 'S':30, 'POD':True, 'polybasis':polyBasis, 'sampler':QS(k0s, "CHEBYSHEV"), 'robustTol':1e-14} theta = - 45. * np.pi / 180 solver = AirfoilScatteringEngine(k0, theta, verbosity = verb, degree_threshold = 8) -if algo == "Pade": +if algo == "RI": params.pop('R') - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) + approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb) else: params.pop('N') params.pop('M') params.pop('polybasis') params.pop('robustTol') - approx = RB(solver, mu0 = k0, approxParameters = params, - verbosity = verb) + approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.setupApprox() if sol == "single": # approx.outParaviewTimeDomainSamples(filename = "out/outSamples", # forceNewFile = False, folders = True) approx.outParaviewTimeDomainApprox(ktar, omega = 2. * np.pi * ktar, filename = "out/outTApp{}".format(ktar), forceNewFile = False, folder = True) approx.outParaviewTimeDomainHF(ktar, omega = 2. * np.pi * ktar, filename = "out/outTHF{}".format(ktar), forceNewFile = False, folder = True) approx.outParaviewTimeDomainErr(ktar, omega = 2. * np.pi * ktar, filename = "out/outTErr{}".format(ktar), forceNewFile = False, folder = True) approx.outParaviewTimeDomainRes(ktar, omega = 2. * np.pi * ktar, filename = "out/outTRes{}".format(ktar), forceNewFile = False, folder = True) appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('Poles:', approx.getPoles()) if sol == "sweep": k0s = np.linspace(k0s[0], k0s[1], Nsweep) kl, kr = min(k0s), max(k0s) approx.samplingEngine.verbosity = 0 approx.trainedModel.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) err = np.zeros_like(normApp) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) err[j] = approx.normErr(k0s[j]) / norm[j] plt.figure() plt.semilogy(k0s, norm) plt.semilogy(k0s, normApp, '--') plt.semilogy(np.real(approx.mus), 1.05*np.max(norm)*np.ones_like(approx.mus, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() polesApp = approx.getPoles() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/all_forcing/all_forcing_engine.py b/examples/all_forcing/all_forcing_engine.py new file mode 100644 index 0000000..85bc985 --- /dev/null +++ b/examples/all_forcing/all_forcing_engine.py @@ -0,0 +1,49 @@ +import numpy as np +import fenics as fen +from rrompy.hfengines.linear_problem import LaplaceBaseProblemEngine as LBPE +from rrompy.utilities.base import verbosityManager as vbMng +from rrompy.solver.fenics import fenics2Vector + +class AllForcingEngine(LBPE): + def __init__(self, mu0:float, n : int = 30, + degree_threshold : int = np.inf, + verbosity : int = 10, timestamp : bool = True): + super().__init__(mu0 = mu0, degree_threshold = degree_threshold, + verbosity = verbosity, timestamp = timestamp) + mesh = fen.RectangleMesh(fen.Point(-5., -5.), fen.Point(5., 5.), n, n) + self.V = fen.FunctionSpace(mesh, "P", 1) + self.nAs, self.nbs = 1, 4 + x, y = fen.SpatialCoordinate(mesh)[:] + scaling = (2. * np.pi) ** -1. + r2 = x ** 2. + y ** 2. + self.forcingCoeffs = [ + scaling * fen.exp(- (r2 + 1. - 2. * x + 1. - 2. * y) / 2. / 4.) / 2., + scaling * fen.exp(- (r2 + 1. + 2. * x + 1. + 2. * y) / 2. / 16.) / 4., + - scaling * fen.exp(- (r2 + 1. + 2. * x + 1. - 2. * y) / 2. / 9.) / 30., + scaling * fen.exp(- (r2 + 1. - 2. * x + 1. + 2. * y) / 2. / 25.) / 120.] + + def b(self, mu = [], der = 0, homogeneized = False): + mu = self.checkParameter(mu) + if not hasattr(der, "__len__"): der = [der] * self.npar + derI = der[0] + nbsTot = self.nbsH if homogeneized else self.nbs + bs = self.bsH if homogeneized else self.bs + if homogeneized and self.mu0 != self.mu0BC: + self.liftDirichletData(self.mu0) + for j in range(derI, nbsTot): + if bs[j] is None: + vbMng(self, "INIT", "Assembling forcing term b{}.".format(j), + 20) + parsRe = self.iterReduceQuadratureDegree([( + self.forcingCoeffs[j], + "forcingCoefficient")]) + u0Re = self.DirichletDatum[0] + L0Re = fen.dot(self.forcingCoeffs[j], self.v) * fen.dx + DBCR = fen.DirichletBC(self.V, u0Re, self.DirichletBoundary) + b = fenics2Vector(L0Re, parsRe, DBCR, 1) + if homogeneized: + self.bsH[j] = b + else: + self.bs[j] = b + vbMng(self, "DEL", "Done assembling forcing term.", 20) + return self._assembleb(mu, der, derI, homogeneized) diff --git a/examples/all_forcing/greedy.py b/examples/all_forcing/greedy.py new file mode 100644 index 0000000..b32a4cc --- /dev/null +++ b/examples/all_forcing/greedy.py @@ -0,0 +1,96 @@ +import numpy as np +from all_forcing_engine import AllForcingEngine +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RI +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RB +from rrompy.solver.fenics import L2NormMatrix +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS + +verb = 5 +timed = False +algo = "RI" +#algo = "RB" +polyBasis = "LEGENDRE" +#polyBasis = "CHEBYSHEV" +#polyBasis = "MONOMIAL" +if timed: verb = 0 + +z0s = np.linspace(-3., 3., 100) +z0 = np.mean(z0s) +zl, zr = min(z0s), max(z0s) + +n = 30 +solver = AllForcingEngine(mu0 = z0, n = n, degree_threshold = 8, verbosity = 0) + +params = {'sampler':QS([zl, zr], "UNIFORM"), 'nTestPoints':500, + 'greedyTol':1e-2, 'S':2, 'polybasis':polyBasis, +# 'errorEstimatorKind':'BARE'} +# 'errorEstimatorKind':'BASIC'} + 'errorEstimatorKind':'EXACT'} + +if algo == "RI": + approx = RI(solver, mu0 = solver.mu0, approxParameters = params, + verbosity = verb) +else: + params.pop("polybasis") + params.pop("errorEstimatorKind") + approx = RB(solver, mu0 = solver.mu0, approxParameters = params, + verbosity = verb) +approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) + +if timed: + from time import clock + start_time = clock() + approx.greedy() + print("Time: ", clock() - start_time) +else: + approx.greedy(True) +polesApp = approx.getPoles() +print("Poles:\n", polesApp) + +approx.samplingEngine.verbosity = 0 +approx.trainedModel.verbosity = 0 +approx.verbosity = 0 +zl, zr = np.real(zl), np.real(zr) +from matplotlib import pyplot as plt +normApp = np.zeros(len(z0s)) +norm = np.zeros_like(normApp) +res = np.zeros_like(normApp) +err = np.zeros_like(normApp) +for j in range(len(z0s)): + normApp[j] = approx.normApprox(z0s[j]) + norm[j] = approx.normHF(z0s[j]) + res[j] = (approx.estimatorNormEngine.norm( + approx.getRes(z0s[j], duality = False)) + / approx.estimatorNormEngine.norm( + approx.getRHS(z0s[j], duality = False))) + err[j] = approx.normErr(z0s[j]) / norm[j] +resApp = approx.errorEstimator(z0s) + +plt.figure() +plt.semilogy(z0s, norm) +plt.semilogy(z0s, normApp, '--') +plt.semilogy(np.real(approx.mus.data), + 1.05*np.max(norm)*np.ones_like(approx.mus.data, dtype = float), + 'rx') +plt.xlim([zl, zr]) +plt.grid() +plt.show() +plt.close() + +plt.figure() +plt.semilogy(z0s, res) +plt.semilogy(z0s, resApp, '--') +plt.semilogy(np.real(approx.mus.data), + approx.greedyTol*np.ones_like(approx.mus.data, dtype = float), + 'rx') +plt.xlim([zl, zr]) +plt.grid() +plt.show() +plt.close() + +plt.figure() +plt.semilogy(z0s, err) +plt.xlim([zl, zr]) +plt.grid() +plt.show() +plt.close() diff --git a/examples/all_forcing/pod.py b/examples/all_forcing/pod.py new file mode 100644 index 0000000..96163e6 --- /dev/null +++ b/examples/all_forcing/pod.py @@ -0,0 +1,88 @@ +import numpy as np +from all_forcing_engine import AllForcingEngine +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS + +verb = 100 +sol = "single" +sol = "sweep" +algo = "RI" +#algo = "RB" +polyBasis = "LEGENDRE" +polyBasis = "CHEBYSHEV" +#polyBasis = "MONOMIAL" + +ztar = 2. +z0s = [-3., 3.] +z0 = np.mean(z0s) + +n = 30 +solver = AllForcingEngine(mu0 = z0, n = n, degree_threshold = 8, verbosity = 0) + +params = {'N':3, 'M':3, 'S':4, 'POD':True, 'polybasis':polyBasis, + 'sampler':QS(z0s, "CHEBYSHEV")} + +if algo == "RI": + approx = RI(solver, mu0 = z0, approxParameters = params, verbosity = verb) +else: + params.pop("N") + params.pop("M") + params.pop("polybasis") + approx = RB(solver, mu0 = z0, approxParameters = params, verbosity = verb) + +approx.setupApprox() +if sol == "single": + approx.plotSamples(what = "REAL") + approx.plotApprox(ztar, what = "REAL", name = "uApp") + approx.plotHF(ztar, what = "REAL", name = "uHF") + approx.plotErr(ztar, what = "REAL", name = "err") + approx.plotRes(ztar, what = "REAL", name = "res") + + appErr, solNorm = approx.normErr(ztar), approx.normHF(ztar) + resNorm, RHSNorm = approx.normRes(ztar), approx.normRHS(ztar) + print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, + np.divide(appErr, solNorm))) + print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, + np.divide(resNorm, RHSNorm))) +poles = approx.getPoles() +print('Poles:', poles) + +if sol == "sweep": + z0s = np.linspace(z0s[0], z0s[1], 100) + zl, zr = min(z0s), max(z0s) + approx.samplingEngine.verbosity = 0 + approx.trainedModel.verbosity = 0 + approx.verbosity = 0 + from matplotlib import pyplot as plt + normRHS = approx.normRHS(z0s) + norm = approx.normHF(z0s) + normApp = approx.normApprox(z0s) + res = approx.normRes(z0s) / normRHS + err = approx.normErr(z0s) / norm + + plt.figure() + plt.semilogy(z0s, norm) + plt.semilogy(z0s, normApp, '--') + plt.semilogy(np.real(approx.mus.data), + 1.05*np.max(norm)*np.ones_like(approx.mus.data, dtype = float), + 'rx') + plt.xlim([zl, zr]) + plt.grid() + plt.show() + plt.close() + + plt.figure() + plt.semilogy(z0s, res) + plt.xlim([zl, zr]) + plt.grid() + plt.show() + plt.close() + + plt.figure() + plt.semilogy(z0s, err) +# plt.semilogy(k0s, errApp) + plt.xlim([zl, zr]) + plt.grid() + plt.show() + plt.close() diff --git a/examples/all_forcing/solver.py b/examples/all_forcing/solver.py new file mode 100644 index 0000000..17d9d1e --- /dev/null +++ b/examples/all_forcing/solver.py @@ -0,0 +1,11 @@ +from all_forcing_engine import AllForcingEngine + +z0 = 0. +ztar = 3. +n = 30 + +solver = AllForcingEngine(mu0 = z0, n = n, degree_threshold = 8, verbosity = 0) +b = solver.b(ztar) +solver.plot(b, what = "REAL", name = "b") +uh = solver.solve(ztar)[0] +solver.plot(uh, what = "REAL") diff --git a/examples/diapason/greedy.py b/examples/diapason/greedy.py index 1d86efe..3121583 100644 --- a/examples/diapason/greedy.py +++ b/examples/diapason/greedy.py @@ -1,178 +1,129 @@ import numpy as np -import fenics as fen -import ufl -from rrompy.hfengines.vector_linear_problem import \ - LinearElasticityHelmholtzProblemEngine as LEHPE -from rrompy.hfengines.vector_linear_problem import \ - LinearElasticityHelmholtzProblemEngineDamped as LEHPED -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB +from diapason_engine import DiapasonEngine, DiapasonEngineDamped +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RI +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RB from rrompy.solver.fenics import L2NormMatrix +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS -verb = 2 +verb = 5 timed = False -algo = "Pade" +algo = "RI" #algo = "RB" polyBasis = "LEGENDRE" -polyBasis = "CHEBYSHEV" +#polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" if timed: verb = 0 dampingEta = 0 * 1e4 / 2. / np.pi k0s = np.linspace(2.5e2, 7.5e3, 100) -k0s = np.linspace(2.5e3, 1.5e4, 100) -k0s = np.linspace(5.0e4, 1.0e5, 100) +#k0s = np.linspace(2.5e3, 1.5e4, 100) +#k0s = np.linspace(5.0e4, 1.0e5, 100) k0s = np.linspace(2.0e5, 2.5e5, 100) -k0 = np.mean(np.power(k0s, 2.)) ** .5 # [Hz] kl, kr = min(k0s), max(k0s) -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':2, 'polybasis':polyBasis, - 'robustTol':2e-16, 'interpRcond':None, 'errorEstimatorKind':'EXACT'} - theta = 20. * np.pi / 180. phi = 10. * np.pi / 180. - -mesh = fen.Mesh("../data/mesh/diapason_1.xml") -subdomains = fen.MeshFunction("size_t", mesh, - "../data/mesh/diapason_1_physical_region.xml") - -meshBall = fen.SubMesh(mesh, subdomains, 2) -meshFork = fen.SubMesh(mesh, subdomains, 1) -Hball = np.max(meshBall.coordinates()[:, 1]) #.00257 -Ltot = np.max(mesh.coordinates()[:, 1]) #.1022 -Lhandle = np.max(meshFork.coordinates()[:, 1]) #.026 -Lrod = Ltot - Lhandle #.0762 -L2var = (Lrod / 4.) ** 2. -Ehandle_ratio = 3. -rhohandle_ratio = 1.5 - c = 3.e2 rho = 8e3 * (2. * np.pi) ** 2. E = 1.93e11 nu = .3 T = 1e6 -lambda_ = E * nu / (1. + nu) / (1. - 2. * nu) -mu_ = E / (1. + nu) - -kWave = (np.cos(theta) * np.cos(phi), np.sin(phi), np.sin(theta) * np.cos(phi)) - -x, y, z = fen.SpatialCoordinate(mesh)[:] -yCorr = y - Ltot -compPlane = kWave[0] * x + kWave[1] * y + kWave[2] * z -xPlane, yPlane, zPlane = (xx - compPlane * xx for xx in (x, y, z)) -xOrtho, yOrtho, zOrtho = (compPlane * xx for xx in (x, y, z)) - -forcingBase = (T / (2. * np.pi * L2var)**.5 - * fen.exp(- (xPlane**2. + yPlane**2. + zPlane**2.) / (2.*L2var))) -forcingWeight = np.real(k0) / c * (xOrtho + yOrtho + zOrtho) -neumannDatum = [ufl.as_vector( - tuple(forcingBase * fen.cos(forcingWeight) * kWavedir for kWavedir in kWave)), - ufl.as_vector( - tuple(forcingBase * fen.sin(forcingWeight) * kWavedir for kWavedir in kWave))] -lambda_eff = ufl.conditional(ufl.ge(y, Lhandle), fen.Constant(lambda_), - fen.Constant(Ehandle_ratio * lambda_)) -mu_eff = ufl.conditional(ufl.ge(y, Lhandle), fen.Constant(mu_), - fen.Constant(Ehandle_ratio * mu_)) -rho_eff = ufl.conditional(ufl.ge(y, Lhandle), fen.Constant(rho), - fen.Constant(rhohandle_ratio * rho)) ### -if dampingEta > 0: - solver = LEHPED(mu0 = np.real(k0), degree_threshold = 8, verbosity = 0) - solver.eta = dampingEta +if np.isclose(dampingEta, 0.): + solver = DiapasonEngine(kappa = np.mean(np.power(k0s, 2.)) ** .5, c = c, + rho = rho, E = E, nu = nu, T = T, theta = theta, + phi = phi, meshNo = 1, degree_threshold = 8, + verbosity = 0) else: - solver = LEHPE(mu0 = np.real(k0), degree_threshold = 8, verbosity = 0) -solver.lambda_ = lambda_eff -solver.mu_ = mu_eff -solver.rho_ = rho_eff -solver.V = fen.VectorFunctionSpace(mesh, "P", 1) -solver.DirichletBoundary = lambda x, on_b: on_b and x[1] < Hball -solver.NeumannBoundary = "REST" -solver.forcingTerm = neumannDatum - -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) + solver = DiapasonEngineDamped(kappa = np.mean(k0s), c = c, rho = rho, + E = E, nu = nu, T = T, theta = theta, + phi = phi, dampingEta = dampingEta, + meshNo = 1, degree_threshold = 8, + verbosity = 0) + +params = {'sampler':QS([kl, kr], "UNIFORM"),#, solver.rescalingExp), + 'nTestPoints':500, 'greedyTol':1e-2, 'S':5, 'polybasis':polyBasis, +# 'errorEstimatorKind':'BARE'} +# 'errorEstimatorKind':'BASIC'} + 'errorEstimatorKind':'EXACT'} + +if algo == "RI": + approx = RI(solver, mu0 = solver.mu0, approxParameters = params, + verbosity = verb) else: - params.pop("Delta") params.pop("polybasis") - params.pop("robustTol") - params.pop("interpRcond") params.pop("errorEstimatorKind") - approx = RB(solver, mu0 = k0, approxParameters = params, + approx = RB(solver, mu0 = solver.mu0, approxParameters = params, verbosity = verb) approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) if timed: from time import clock start_time = clock() approx.greedy() print("Time: ", clock() - start_time) else: approx.greedy(True) polesApp = approx.getPoles() print("Poles:\n", polesApp) approx.samplingEngine.verbosity = 0 +approx.trainedModel.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) res = np.zeros_like(normApp) err = np.zeros_like(normApp) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(k0s[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(k0s[j]))) + res[j] = (approx.estimatorNormEngine.norm( + approx.getRes(k0s[j], duality = False)) + / approx.estimatorNormEngine.norm( + approx.getRHS(k0s[j], duality = False))) err[j] = approx.normErr(k0s[j]) / norm[j] resApp = approx.errorEstimator(k0s) -res[res < 1e-5 * approx.greedyTol] = np.nan -resApp[resApp < 1e-5 * approx.greedyTol] = np.nan -err[err < 1e-8 * approx.greedyTol] = np.nan - plt.figure() plt.semilogy(k0s, norm) plt.semilogy(k0s, normApp, '--') -plt.semilogy(np.real(approx.mus), - 1.05*np.max(norm)*np.ones_like(approx.mus, dtype = float), +plt.semilogy(np.real(approx.mus.data), + 1.05*np.max(norm)*np.ones_like(approx.mus.data, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, res) plt.semilogy(k0s, resApp, '--') -plt.semilogy(np.real(approx.mus), - approx.greedyTol*np.ones_like(approx.mus, dtype = float), +plt.semilogy(np.real(approx.mus.data), + approx.greedyTol*np.ones_like(approx.mus.data, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesAppEff = polesApp[~mask] plt.figure() plt.plot(np.real(polesAppEff), np.imag(polesAppEff), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/diapason/pod.py b/examples/diapason/pod.py index 3c69eb2..1ba8e43 100644 --- a/examples/diapason/pod.py +++ b/examples/diapason/pod.py @@ -1,149 +1,147 @@ import numpy as np from diapason_engine import DiapasonEngine, DiapasonEngineDamped -from rrompy.reduction_methods.distributed import RationalInterpolant as Pade -from rrompy.reduction_methods.distributed import RBDistributed as RB +from rrompy.reduction_methods.standard import RationalInterpolant as Pade +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS verb = 100 sol = "single" sol = "sweep" algo = "Pade" #algo = "RB" polyBasis = "LEGENDRE" polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" dampingEta = 0. * 1e4 / 2. / np.pi ktar = 1.e4 # [Hz] k0s = [2.5e2, 1.0e4] #k0s = np.array([2.5e3, 1.5e4]) #k0s = np.array([5.0e4, 1.0e5]) k0s = [2.0e5, 3.0e5] k0 = np.mean(np.power(k0s, 2.)) ** .5 theta = 20. * np.pi / 180. phi = 10. * np.pi / 180. c = 3.e2 rho = 8e3 * (2. * np.pi) ** 2. E = 1.93e11 nu = .3 T = 1e6 ### if np.isclose(dampingEta, 0.): - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) + rescalingExp = 2. solver = DiapasonEngine(kappa = k0, c = c, rho = rho, E = E, nu = nu, T = T, theta = theta, phi = phi, meshNo = 1, degree_threshold = 8, verbosity = 0) else: - rescaling = lambda x: x - rescalingInv = lambda x: x + rescalingExp = 1. solver = DiapasonEngineDamped(kappa = k0, c = c, rho = rho, E = E, nu = nu, T = T, theta = theta, phi = phi, dampingEta = dampingEta, meshNo = 1, degree_threshold = 8, verbosity = 0) params = {'N':39, 'M':39, 'S':40, 'POD':True, 'polybasis':polyBasis, - 'sampler':QS(k0s, "CHEBYSHEV", rescaling, rescalingInv)}#, + 'sampler':QS(k0s, "CHEBYSHEV", rescalingExp)}#, # 'robustTol':1e-16} if algo == "Pade": approx = Pade(solver, mu0 = k0, approxParameters = params, verbosity = verb) else: params.pop("N") params.pop("M") params.pop("polybasis") # params.pop("robustTol") approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.setupApprox() if sol == "single": approx.outParaviewTimeDomainSamples( filename = "out/outSamples{}".format(dampingEta), forceNewFile = False, folders = True) nameBase = "{}_{}".format(ktar, dampingEta) approx.outParaviewTimeDomainApprox(ktar, omega = 2. * np.pi * ktar, filename = "out/outTApp{}".format(nameBase), forceNewFile = False, folder = True) approx.outParaviewTimeDomainHF(ktar, omega = 2. * np.pi * ktar, filename = "out/outTHF{}".format(nameBase), forceNewFile = False, folder = True) approx.outParaviewTimeDomainErr(ktar, omega = 2. * np.pi * ktar, filename = "out/outTErr{}".format(nameBase), forceNewFile = False, folder = True) approx.outParaviewTimeDomainRes(ktar, omega = 2. * np.pi * ktar, filename = "out/outTRes{}".format(nameBase), forceNewFile = False, folder = True) appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) poles = approx.getPoles() print('Poles:', poles) if sol == "sweep": k0s = np.linspace(k0s[0], k0s[1], 100) kl, kr = min(k0s), max(k0s) approx.samplingEngine.verbosity = 0 approx.trainedModel.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) err = np.zeros_like(normApp) res = np.zeros_like(normApp) # errApp = np.zeros_like(normApp) fNorm = approx.normRHS(k0s[0]) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) err[j] = approx.normErr(k0s[j]) / norm[j] res[j] = approx.normRes(k0s[j]) / fNorm # errApp[j] = res[j] / np.min(np.abs(k0s[j] - poles)) # errApp *= np.mean(err) / np.mean(errApp) plt.figure() plt.semilogy(k0s, norm) plt.semilogy(k0s, normApp, '--') plt.semilogy(np.real(approx.mus), 1.05*np.max(norm)*np.ones_like(approx.mus, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, res) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) # plt.semilogy(k0s, errApp) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() polesApp = approx.getPoles() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/diapason/solver.py b/examples/diapason/solver.py index 9cf3c78..715756b 100644 --- a/examples/diapason/solver.py +++ b/examples/diapason/solver.py @@ -1,36 +1,32 @@ import numpy as np from diapason_engine import DiapasonEngine, DiapasonEngineDamped verb = 2 dampingEta = 0 * 1e4 / 2. / np.pi k0 = 1.8e3 # [Hz] ktar = 1.8e3 # [Hz] theta = 20. * np.pi / 180. phi = 10. * np.pi / 180. c = 3.e2 rho = 8e3 * (2. * np.pi) ** 2. E = 1.93e11 nu = .3 T = 1e6 ### if np.isclose(dampingEta, 0.): - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) solver = DiapasonEngine(kappa = k0, c = c, rho = rho, E = E, nu = nu, T = T, theta = theta, phi = phi, meshNo = 1, degree_threshold = 8, verbosity = 0) else: - rescaling = lambda x: x - rescalingInv = lambda x: x solver = DiapasonEngineDamped(kappa = k0, c = c, rho = rho, E = E, nu = nu, T = T, theta = theta, phi = phi, dampingEta = dampingEta, meshNo = 1, degree_threshold = 8, verbosity = 0) uh = solver.solve(ktar)[0] solver.outParaviewTimeDomain(uh, omega = 2. * np.pi * ktar, filename = "out/outT{}_{}_".format(ktar, dampingEta), forceNewFile = False) diff --git a/examples/from_papers/greedy_internalBox.py b/examples/from_papers/greedy_internalBox.py index 3ec5bbe..caa2d7f 100644 --- a/examples/from_papers/greedy_internalBox.py +++ b/examples/from_papers/greedy_internalBox.py @@ -1,111 +1,114 @@ import numpy as np import fenics as fen from rrompy.hfengines.linear_problem import HelmholtzProblemEngine as HPE -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RI +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RB from rrompy.solver.fenics import L2NormMatrix +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS dim = 3 -verb = 2 +verb = 5 timed = False -algo = "Pade" -algo = "RB" +algo = "RI" +#algo = "RB" polyBasis = "LEGENDRE" #polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" k0s = np.power(np.linspace(500 ** 2., 2250 ** 2., 200), .5) k0 = np.mean(np.power(k0s, 2.)) ** .5 kl, kr = min(k0s), max(k0s) -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':2, 'basis':polyBasis} +params = {'sampler':QS([kl, kr], "UNIFORM", 2.), 'nTestPoints':500, + 'greedyTol':1e-2, 'S':2, 'polybasis':polyBasis, + 'errorEstimatorKind':'BASIC'} if dim == 2: mesh = fen.RectangleMesh(fen.Point(0., 0.), fen.Point(.1, .15), 10, 15) x, y = fen.SpatialCoordinate(mesh)[:] f = fen.exp(- 1e2 * (x + y)) else:#if dim == 3: mesh = fen.BoxMesh(fen.Point(0., 0., 0.), fen.Point(.1, .15, .25), 4, 6,10) x, y, z = fen.SpatialCoordinate(mesh)[:] f = fen.exp(- 1e2 * (x + y + z)) solver = HPE(np.real(k0), verbosity = verb) solver.V = fen.FunctionSpace(mesh, "P", 3) solver.refractionIndex = fen.Constant(1. / 54.6) solver.forcingTerm = f solver.NeumannBoundary = "ALL" ######### -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) +if algo == "RI": + approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb) else: + params.pop("polybasis") + params.pop("errorEstimatorKind") approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) if timed: from time import clock start_time = clock() approx.greedy() print("Time: ", clock() - start_time) else: approx.greedy(True) approx.samplingEngine.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) res = np.zeros_like(normApp) err = np.zeros_like(normApp) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(k0s[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(k0s[j]))) + res[j] = (approx.estimatorNormEngine.norm( + approx.getRes(k0s[j], duality = False)) + / approx.estimatorNormEngine.norm( + approx.getRHS(k0s[j], duality = False))) err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) resApp = approx.errorEstimator(k0s) plt.figure() plt.plot(k0s, norm) plt.plot(k0s, normApp, '--') plt.plot(np.real(approx.mus(0)), 1.05*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, res) plt.semilogy(k0s, resApp, '--') plt.semilogy(np.real(approx.mus(0)), 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() polesApp = approx.getPoles() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/from_papers/greedy_scatteringAirfoil.py b/examples/from_papers/greedy_scatteringAirfoil.py index 5b5bd75..ade4b37 100644 --- a/examples/from_papers/greedy_scatteringAirfoil.py +++ b/examples/from_papers/greedy_scatteringAirfoil.py @@ -1,149 +1,153 @@ import numpy as np import fenics as fen import ufl from rrompy.hfengines.linear_problem import \ HelmholtzBoxScatteringProblemEngine as HSP -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RI +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RB from rrompy.solver.fenics import fenONE, L2NormMatrix +from rrompy.parameter.parameter_sampling import QuadratureSampler as QS verb = 2 timed = False -algo = "Pade" +algo = "RI" #algo = "RB" polyBasis = "LEGENDRE" #polyBasis = "CHEBYSHEV" #polyBasis = "MONOMIAL" homog = True homog = False k0s = np.linspace(5, 20, 25) k0 = np.mean(k0s) kl, kr = min(k0s), max(k0s) -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':2, 'polybasis':polyBasis} +params = {'sampler':QS([kl, kr], "UNIFORM"), 'nTestPoints':500, + 'greedyTol':1e-2, 'S':10, 'polybasis':polyBasis, + 'errorEstimatorKind':'BARE'} +# 'errorEstimatorKind':'BASIC'} +# 'errorEstimatorKind':'EXACT'} ######### PI = np.pi R = 2 def Dboundary(x, on_boundary): return on_boundary and (x[0]**2+x[1]**2)**.5 < .95 * R kappa = 10 theta = PI * - 45 / 180. mu = 1.1 epsilon = .1 mesh = fen.Mesh('../data/mesh/airfoil.xml') c, s = np.cos(theta), np.sin(theta) x, y = fen.SpatialCoordinate(mesh)[:] u0R = - fen.cos(kappa * (c * x + s * y)) u0I = - fen.sin(kappa * (c * x + s * y)) checkReal = x**2-x+y**2 rhop5 = ((x**2+y**2)/((x-1)**2+y**2))**.25 phiroot1 = fen.atan(-y/(x**2-x+y**2)) / 2 phiroot2 = fen.atan(-y/(x**2-x+y**2)) / 2 - PI * ufl.sign(-y/(x**2-x+y**2)) / 2 kappam1 = (((rhop5*fen.cos(phiroot1)+.5)**2.+(rhop5*fen.sin(phiroot1))**2.)/ ((rhop5*fen.cos(phiroot1)-1.)**2.+(rhop5*fen.sin(phiroot1))**2.) )**.5 - mu kappam2 = (((rhop5*fen.cos(phiroot2)+.5)**2.+(rhop5*fen.sin(phiroot2))**2.)/ ((rhop5*fen.cos(phiroot2)-1.)**2.+(rhop5*fen.sin(phiroot2))**2.) )**.5 - mu Heps1 = .9 * .5 * (1 + kappam1/epsilon + fen.sin(PI*kappam1/epsilon) / PI) + .1 Heps2 = .9 * .5 * (1 + kappam2/epsilon + fen.sin(PI*kappam2/epsilon) / PI) + .1 cTT = ufl.conditional(ufl.le(kappam1, epsilon), Heps1, fenONE) c_F = fen.Constant(.1) cFT = ufl.conditional(ufl.le(kappam2, epsilon), Heps2, fenONE) c_F = fen.Constant(.1) cT = ufl.conditional(ufl.ge(kappam1, - epsilon), cTT, c_F) cF = ufl.conditional(ufl.ge(kappam2, - epsilon), cFT, c_F) a = ufl.conditional(ufl.ge(checkReal, 0.), cT, cF) solver = HSP(R, np.real(k0), theta, n = 1, verbosity = verb, degree_threshold = 8) solver.omega = np.real(k0) -solver.V = fen.FunctionSpace(mesh, "P", 3) +solver.V = fen.FunctionSpace(mesh, "P", 2) solver.diffusivity = a solver.DirichletBoundary = Dboundary solver.RobinBoundary = "REST" solver.DirichletDatum = [u0R, u0I] ######### -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb, homogeneized = homog) +if algo == "RI": + approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, + homogeneized = homog) else: + params.pop("polybasis") + params.pop("errorEstimatorKind") approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) if timed: from time import clock start_time = clock() approx.greedy() print("Time: ", clock() - start_time) else: approx.greedy(True) approx.samplingEngine.verbosity = 0 approx.verbosity = 0 kl, kr = np.real(kl), np.real(kr) from matplotlib import pyplot as plt normApp = np.zeros(len(k0s)) norm = np.zeros_like(normApp) res = np.zeros_like(normApp) err = np.zeros_like(normApp) for j in range(len(k0s)): normApp[j] = approx.normApprox(k0s[j]) norm[j] = approx.normHF(k0s[j]) res[j] = (approx.estimatorNormEngine.norm( - approx.getRes(k0s[j], homogeneized=homog)) + approx.getRes(k0s[j], homogeneized = homog, duality = False)) / approx.estimatorNormEngine.norm( - approx.getRHS(k0s[j], homogeneized=homog))) + approx.getRHS(k0s[j], homogeneized = homog, duality = False))) err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) resApp = approx.errorEstimator(k0s) plt.figure() plt.plot(k0s, norm) plt.plot(k0s, normApp, '--') plt.plot(np.real(approx.mus(0)), 1.05*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, res) plt.semilogy(k0s, resApp, '--') plt.semilogy(np.real(approx.mus(0)), 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() plt.figure() plt.semilogy(k0s, err) plt.xlim([kl, kr]) plt.grid() plt.show() plt.close() polesApp = approx.getPoles() mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/from_papers/pod_scatteringAirfoil.py b/examples/from_papers/pod_scatteringAirfoil.py index 7d578cb..d0cf6b4 100644 --- a/examples/from_papers/pod_scatteringAirfoil.py +++ b/examples/from_papers/pod_scatteringAirfoil.py @@ -1,132 +1,132 @@ import numpy as np import fenics as fen import ufl from rrompy.hfengines.linear_problem import \ HelmholtzBoxScatteringProblemEngine as HSP -from rrompy.reduction_methods.distributed import RationalInterpolant as PD -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS from rrompy.solver.fenics import fenONE from operator import itemgetter def subdict(d, ks): return dict(zip(ks, itemgetter(*ks)(d))) verb = 0 #################### homog = True #homog = False #################### test = "solve" -test = "Distributed" +test = "approx" plotSamples = True k0 = 10 kLeft, kRight = 8 + 0.j, 12 + 0.j ktar = 11 ktars = np.linspace(8, 12, 21) + 0.j PI = np.pi R = 2 def Dboundary(x, on_boundary): return on_boundary and (x[0]**2+x[1]**2)**.5 < .95 * R kappa = 10 theta = PI * - 45 / 180. mu = 1.1 epsilon = .1 mesh = fen.Mesh('../data/mesh/airfoil.xml') c, s = np.cos(theta), np.sin(theta) x, y = fen.SpatialCoordinate(mesh)[:] u0R = - fen.cos(kappa * (c * x + s * y)) u0I = - fen.sin(kappa * (c * x + s * y)) checkReal = x**2-x+y**2 rhop5 = ((x**2+y**2)/((x-1)**2+y**2))**.25 phiroot1 = fen.atan(-y/(x**2-x+y**2)) / 2 phiroot2 = fen.atan(-y/(x**2-x+y**2)) / 2 - PI * ufl.sign(-y/(x**2-x+y**2)) / 2 kappam1 = (((rhop5*fen.cos(phiroot1)+.5)**2.+(rhop5*fen.sin(phiroot1))**2.)/ ((rhop5*fen.cos(phiroot1)-1.)**2.+(rhop5*fen.sin(phiroot1))**2.) )**.5 - mu kappam2 = (((rhop5*fen.cos(phiroot2)+.5)**2.+(rhop5*fen.sin(phiroot2))**2.)/ ((rhop5*fen.cos(phiroot2)-1.)**2.+(rhop5*fen.sin(phiroot2))**2.) )**.5 - mu Heps1 = .9 * .5 * (1 + kappam1/epsilon + fen.sin(PI*kappam1/epsilon) / PI) + .1 Heps2 = .9 * .5 * (1 + kappam2/epsilon + fen.sin(PI*kappam2/epsilon) / PI) + .1 cTT = ufl.conditional(ufl.le(kappam1, epsilon), Heps1, fenONE) c_F = fen.Constant(.1) cFT = ufl.conditional(ufl.le(kappam2, epsilon), Heps2, fenONE) c_F = fen.Constant(.1) cT = ufl.conditional(ufl.ge(kappam1, - epsilon), cTT, c_F) cF = ufl.conditional(ufl.ge(kappam2, - epsilon), cFT, c_F) a = ufl.conditional(ufl.ge(checkReal, 0.), cT, cF) ### solver = HSP(R, np.abs(k0), theta, n = 1, verbosity = verb, degree_threshold = 8) solver.V = fen.FunctionSpace(mesh, "P", 3) solver.diffusivity = a solver.DirichletBoundary = Dboundary solver.RobinBoundary = "REST" solver.DirichletDatum = [u0R, u0I] ### if test == "solve": uinc = solver.liftDirichletData(k0) if homog: uhtot = solver.solve(k0, homogeneized = homog)[0] uh = uhtot + uinc else: uh = solver.solve(k0, homogeneized = homog)[0] uhtot = uh - uinc print(solver.norm(uh)) print(solver.norm(uhtot)) solver.plot(fen.project(a, solver.V).vector(), what = 'Real', name = 'a') solver.plot(uinc, what = 'Real', name = 'u_inc') solver.plot(uh, what = 'ABS') solver.plot(uhtot, what = 'ABS', name = 'u + u_inc') -elif test == "Distributed": +elif test == "approx": params = {'N':8, 'M':8, 'R':9, 'S':9, 'POD':True, 'polybasis':"CHEBYSHEV", 'sampler':QS([kLeft, kRight], "CHEBYSHEV")} - parPade = subdict(params, ['N', 'M', 'S', 'POD', 'polybasis', + parRI = subdict(params, ['N', 'M', 'S', 'POD', 'polybasis', 'sampler']) parRB = subdict(params, ['R', 'S', 'POD', 'sampler']) - approxPade = PD(solver, mu0 = np.mean([kLeft, kRight]), - approxParameters = parPade, verbosity = verb, - homogeneized = homog) - approxRB = RBD(solver, mu0 = np.mean([kLeft, kRight]), - approxParameters = parRB, verbosity = verb, - homogeneized = homog) - - approxPade.setupApprox() + approxRI = RI(solver, mu0 = np.mean([kLeft, kRight]), + approxParameters = parRI, verbosity = verb, + homogeneized = homog) + approxRB = RB(solver, mu0 = np.mean([kLeft, kRight]), + approxParameters = parRB, verbosity = verb, + homogeneized = homog) + + approxRI.setupApprox() approxRB.setupApprox() if plotSamples: - approxPade.plotSamples() - approxPade.plotHF(ktar, name = 'u_HF') - approxPade.plotApprox(ktar, name = 'u_Pade''') - approxPade.plotErr(ktar, name = 'err_Pade''') - approxPade.plotRes(ktar, name = 'res_Pade''') + approxRI.plotSamples() + approxRI.plotHF(ktar, name = 'u_HF') + approxRI.plotApprox(ktar, name = 'u_RI''') + approxRI.plotErr(ktar, name = 'err_RI''') + approxRI.plotRes(ktar, name = 'res_RI''') approxRB.plotApprox(ktar, name = 'u_RB') approxRB.plotErr(ktar, name = 'err_RB') approxRB.plotRes(ktar, name = 'res_RB') - HFNorm, RHSNorm = approxPade.normHF(ktar), approxPade.normRHS(ktar) - PadeRes, PadeErr = approxPade.normRes(ktar), approxPade.normErr(ktar) + HFNorm, RHSNorm = approxRI.normHF(ktar), approxRI.normRHS(ktar) + RIRes, RIErr = approxRI.normRes(ktar), approxRI.normErr(ktar) RBRes, RBErr = approxRB.normRes(ktar), approxRB.normErr(ktar) print('HFNorm:\t{}\nRHSNorm:\t{}'.format(HFNorm, RHSNorm)) - print('PadeRes:\t{}\nPadeErr:\t{}'.format(PadeRes, PadeErr)) + print('RIRes:\t{}\nRIErr:\t{}'.format(RIRes, RIErr)) print('RBRes:\t{}\nRBErr:\t{}'.format(RBRes, RBErr)) - print('\nPoles Pade'':') - print(approxPade.getPoles()) + print('\nPoles RI'':') + print(approxRI.getPoles()) diff --git a/examples/greedy/matrix_greedy.py b/examples/greedy/matrix_greedy.py deleted file mode 100644 index c8e5db2..0000000 --- a/examples/greedy/matrix_greedy.py +++ /dev/null @@ -1,113 +0,0 @@ -import numpy as np -import scipy.sparse as sp -from matplotlib import pyplot as plt -from rrompy.hfengines.base import MatrixEngineBase as MEB -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB - -test = 1 -timed = False -method = "Pade" -method = "RB" -verb = 200 -errorEstimatorKind = "BARE" -#errorEstimatorKind = "BASIC" -#errorEstimatorKind = "EXACT" - -N = 100 -solver = MEB(verbosity = verb) -solver.npar = 1 -solver.nAs = 2 -if test == 1: - solver.As = [sp.spdiags([np.arange(1, 1 + N)], [0], N, N), - - sp.eye(N)] -elif test == 2: - solver.setSolver("SOLVE") - fftB = np.fft.fft(np.eye(N)) * N**-.5 - solver.As = [fftB.dot(np.multiply(np.arange(1, 1 + N), fftB.conj()).T), - - np.eye(N)] -np.random.seed(420) -solver.nbs = 1 -solver.bs = [np.random.randn(N) + 1.j * np.random.randn(N)] - -mu0 = 10.25 -murange = [1.25, 19.25] -mutars = np.linspace(murange[0], murange[1], 500) -if method == "Pade": - params = {'muBounds':murange, 'nTestPoints':200, 'Delta':0, 'S':5, - 'greedyTol':1e-2, 'polybasis':"CHEBYSHEV", - 'errorEstimatorKind':errorEstimatorKind} - approx = Pade(solver, mu0 = mu0, approxParameters = params, - verbosity = verb) -elif method == "RB": - params = {'muBounds':murange, 'nTestPoints':500, 'greedyTol':1e-2, 'S':5} - approx = RB(solver, mu0 = mu0, approxParameters = params, - verbosity = verb) - -if timed: - from time import clock - start_time = clock() - approx.greedy() - print("Time: ", clock() - start_time) -else: - approx.greedy(True) - - -approx.samplingEngine.verbosity = 0 -approx.trainedModel.verbosity = 0 -approx.verbosity = 0 -normApp = np.zeros(len(mutars)) -norm = np.zeros_like(normApp) -res = np.zeros_like(normApp) -err = np.zeros_like(normApp) -for j in range(len(mutars)): - normApp[j] = approx.normApprox(mutars[j]) - norm[j] = approx.normHF(mutars[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(mutars[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(mutars[j]))) - err[j] = approx.normErr(mutars[j]) / approx.normHF(mutars[j]) -resApp = approx.errorEstimator(mutars) - -plt.figure() -plt.semilogy(mutars, norm) -plt.semilogy(mutars, normApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 1.25*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim(murange) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(mutars, res) -plt.semilogy(mutars, resApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim(murange) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(mutars, err) -plt.xlim(murange) -plt.grid() -plt.show() -plt.close() - -polesTrue = np.arange(1, 1 + N) -polesTrue = polesTrue[polesTrue >= murange[0]] -polesTrue = polesTrue[polesTrue <= murange[1]] -polesApp = approx.getPoles() -mask = (np.real(polesApp) < murange[0]) | (np.real(polesApp) > murange[1]) -print("Outliers:", polesApp[mask]) -polesApp = polesApp[~mask] -plt.figure() -plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') -plt.plot(polesTrue, np.zeros_like(polesTrue), 'm.') -plt.axis('equal') -plt.grid() -plt.show() -plt.close() diff --git a/examples/greedy/parametricDomain.py b/examples/greedy/parametricDomain.py deleted file mode 100644 index 7284438..0000000 --- a/examples/greedy/parametricDomain.py +++ /dev/null @@ -1,105 +0,0 @@ -import numpy as np -from rrompy.hfengines.linear_problem import \ - HelmholtzSquareBubbleDomainProblemEngine as HSBDPE -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB -from rrompy.solver.fenics import L2NormMatrix - -verb = 2 -timed = False -algo = "Pade" -algo = "RB" -polyBasis = "LEGENDRE" -polyBasis = "CHEBYSHEV" -#polyBasis = "MONOMIAL" -errorEstimatorKind = "BARE" -#errorEstimatorKind = "BASIC" -#errorEstimatorKind = "EXACT" - -k0s = np.power(np.linspace(9, 19, 100), .5) -k0 = np.mean(np.power(k0s, 2.)) ** .5 -kl, kr = min(k0s), max(k0s) - -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':2, 'polybasis':polyBasis, - 'errorEstimatorKind':errorEstimatorKind} - -if timed: - verb = 0 - -solver = HSBDPE(kappa = 12 ** .5, theta = np.pi / 3, n = 20, mu0 = k0, - degree_threshold = 15, verbosity = verb) -solver.omega = np.real(k0) - -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) -else: - params.pop('Delta') - params.pop('polybasis') - params.pop('errorEstimatorKind') - approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) -approx.initEstimatorNormEngine(np.abs(k0) ** 2. * L2NormMatrix(solver.V)) - -if timed: - from time import clock - start_time = clock() - approx.greedy() - print("Time: ", clock() - start_time) -else: - approx.greedy(True) - -approx.samplingEngine.verbosity = 0 -approx.verbosity = 0 -from matplotlib import pyplot as plt -normApp = np.zeros(len(k0s)) -norm = np.zeros_like(normApp) -res = np.zeros_like(normApp) -err = np.zeros_like(normApp) -for j in range(len(k0s)): - normApp[j] = approx.normApprox(k0s[j]) - norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(k0s[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(k0s[j]))) - err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) -resApp = approx.errorEstimator(k0s) - -plt.figure() -plt.semilogy(k0s, norm) -plt.semilogy(k0s, normApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 1.25*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, res) -plt.semilogy(k0s, resApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, err) -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -polesApp = approx.getPoles() -mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) -print("Outliers:", polesApp[mask]) -polesApp = polesApp[~mask] -plt.figure() -plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') -plt.axis('equal') -plt.grid() -plt.show() -plt.close() diff --git a/examples/greedy/squareBubbleHomog.py b/examples/greedy/squareBubbleHomog.py deleted file mode 100644 index c639459..0000000 --- a/examples/greedy/squareBubbleHomog.py +++ /dev/null @@ -1,117 +0,0 @@ -import numpy as np -from rrompy.hfengines.linear_problem import \ - HelmholtzSquareBubbleProblemEngine as HSBPE -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB -from rrompy.utilities.numerical import squareResonances -from rrompy.solver.fenics import L2NormMatrix - -verb = 2 -timed = False -algo = "Pade" -#algo = "RB" -polyBasis = "LEGENDRE" -#polyBasis = "CHEBYSHEV" -#polyBasis = "MONOMIAL" -errorEstimatorKind = "BARE" -#errorEstimatorKind = "BASIC" -#errorEstimatorKind = "EXACT" - -k0s = np.power(np.linspace(95, 149, 250), .5) -#k0s = np.power(np.linspace(95, 129, 100), .5) -#k0s = np.power(np.linspace(95, 109, 100), .5) -k0 = np.mean(np.power(k0s, 2.)) ** .5 -kl, kr = min(k0s), max(k0s) - -polesexact = np.unique(np.power(squareResonances(kl**2., kr**2., False), .5)) - -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':10, 'polybasis':polyBasis, - 'errorEstimatorKind':errorEstimatorKind, 'interactive':False} - -if timed: - verb = 0 - -solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 20, - verbosity = verb) -solver.omega = np.real(k0) -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) -else: - params.pop('Delta') - params.pop('polybasis') - params.pop('errorEstimatorKind') - approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) -approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) - -if timed: - from time import clock - start_time = clock() - approx.greedy() - print("Time: ", clock() - start_time) -else: - approx.greedy(True) - -approx.samplingEngine.verbosity = 0 -approx.trainedModel.verbosity = 0 -approx.verbosity = 0 -from matplotlib import pyplot as plt -normApp = np.zeros_like(k0s) -norm = np.zeros_like(k0s) -res = np.zeros_like(k0s) -err = np.zeros_like(k0s) -for j in range(len(k0s)): - normApp[j] = approx.normApprox(k0s[j]) - norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(k0s[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(k0s[j]))) - err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) -resApp = approx.errorEstimator(k0s) - -plt.figure() -plt.semilogy(k0s, norm) -plt.semilogy(k0s, normApp, '--') -plt.semilogy(polesexact, - 2.*np.max(norm)*np.ones_like(polesexact, dtype = float), 'm.') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, res) -plt.semilogy(k0s, resApp, '--') -plt.semilogy(polesexact, - 2.*np.max(resApp)*np.ones_like(polesexact, dtype = float), 'm.') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, err) -plt.semilogy(polesexact, - 2.*np.max(err)*np.ones_like(polesexact, dtype = float), 'm.') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -polesApp = approx.getPoles() -mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) -print("Outliers:", polesApp[mask]) -polesApp = polesApp[~mask] -plt.figure() -plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') -plt.plot(np.real(polesexact), np.imag(polesexact), 'm.') -plt.axis('equal') -plt.grid() -plt.show() -plt.close() diff --git a/examples/greedy/squareScatteringHomog.py b/examples/greedy/squareScatteringHomog.py deleted file mode 100644 index a32cb08..0000000 --- a/examples/greedy/squareScatteringHomog.py +++ /dev/null @@ -1,104 +0,0 @@ -import numpy as np -from rrompy.hfengines.linear_problem import \ - HelmholtzCavityScatteringProblemEngine as HCSPE -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB -from rrompy.solver.fenics import L2NormMatrix - -verb = 2 -timed = False -algo = "Pade" -algo = "RB" -polyBasis = "LEGENDRE" -polyBasis = "CHEBYSHEV" -#polyBasis = "MONOMIAL" -errorEstimatorKind = "BARE" -errorEstimatorKind = "BASIC" -#errorEstimatorKind = "EXACT" - -k0s = np.linspace(10, 15, 100) -k0 = np.mean(k0s) -kl, kr = min(k0s), max(k0s) - -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':5e-3, 'S':2, 'polybasis':polyBasis, - 'errorEstimatorKind':errorEstimatorKind} - -if timed: - verb = 0 - -solver = HCSPE(kappa = 5, n = 20, verbosity = verb) -solver.omega = np.real(k0) -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb) -else: - params.pop('Delta') - params.pop('polybasis') - params.pop('errorEstimatorKind') - approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) -approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) - -if timed: - from time import clock - start_time = clock() - approx.greedy() - print("Time: ", clock() - start_time) -else: - approx.greedy(True) - -approx.samplingEngine.verbosity = 0 -approx.trainedModel.verbosity = 0 -approx.verbosity = 0 -from matplotlib import pyplot as plt -normApp = np.zeros(len(k0s)) -norm = np.zeros_like(normApp) -res = np.zeros_like(normApp) -err = np.zeros_like(normApp) -for j in range(len(k0s)): - normApp[j] = approx.normApprox(k0s[j]) - norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm(approx.getRes(k0s[j])) - / approx.estimatorNormEngine.norm(approx.getRHS(k0s[j]))) - err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) -resApp = approx.errorEstimator(k0s) - -plt.figure() -plt.plot(k0s, norm) -plt.plot(k0s, normApp, '--') -plt.plot(np.real(approx.mus(0)), - 1.25*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, res) -plt.semilogy(k0s, resApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, err) -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -polesApp = approx.getPoles() -mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) -print("Outliers:", polesApp[mask]) -polesApp = polesApp[~mask] -plt.figure() -plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') -plt.axis('equal') -plt.grid() -plt.show() -plt.close() diff --git a/examples/greedy/squareTransmissionNonHomog.py b/examples/greedy/squareTransmissionNonHomog.py deleted file mode 100644 index f729c20..0000000 --- a/examples/greedy/squareTransmissionNonHomog.py +++ /dev/null @@ -1,116 +0,0 @@ -import numpy as np -from rrompy.hfengines.linear_problem import \ - HelmholtzSquareTransmissionProblemEngine as HSTPE -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as Pade -from rrompy.reduction_methods.distributed_greedy import \ - RBDistributedGreedy as RB -from rrompy.solver.fenics import L2NormMatrix - -timed = False -verb = 2 -algo = "Pade" -#algo = "RB" -polyBasis = "LEGENDRE" -#polyBasis = "CHEBYSHEV" -#polyBasis = "MONOMIAL" -homog = True -#homog = False -errorEstimatorKind = "BARE" -errorEstimatorKind = "BASIC" -#errorEstimatorKind = "EXACT" - -k0s = np.power(np.linspace(4, 15, 100), .5) -k0 = np.mean(np.power(k0s, 2.)) ** .5 -kl, kr = min(k0s), max(k0s) - -rescaling = lambda x: np.power(x, 2.) -rescalingInv = lambda x: np.power(x, .5) -params = {'muBounds':[kl, kr], 'nTestPoints':500, 'Delta':0, - 'greedyTol':1e-2, 'S':5, 'polybasis':polyBasis, - 'errorEstimatorKind':errorEstimatorKind} - -solver = HSTPE(nT = 1, nB = 2, theta = np.pi * 20 / 180, kappa = 4., - n = 20, verbosity = verb) -solver.omega = np.real(k0) -if algo == "Pade": - approx = Pade(solver, mu0 = k0, approxParameters = params, - verbosity = verb, homogeneized = homog) -else: - params.pop('Delta') - params.pop('polybasis') - params.pop('errorEstimatorKind') - approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb, - homogeneized = homog) -approx.initEstimatorNormEngine(L2NormMatrix(solver.V)) - -if timed: - from time import clock - start_time = clock() - approx.greedy() - print("Time: ", clock() - start_time) -else: - approx.greedy(True) - -approx.samplingEngine.verbosity = 0 -approx.verbosity = 0 -from matplotlib import pyplot as plt -normApp = np.zeros(len(k0s)) -norm = np.zeros_like(normApp) -res = np.zeros_like(normApp) -err = np.zeros_like(normApp) -for j in range(len(k0s)): - normApp[j] = approx.normApprox(k0s[j]) - norm[j] = approx.normHF(k0s[j]) - res[j] = (approx.estimatorNormEngine.norm( - approx.getRes(k0s[j], homogeneized=homog)) - / approx.estimatorNormEngine.norm( - approx.getRHS(k0s[j], homogeneized=homog))) - err[j] = approx.normErr(k0s[j]) / approx.normHF(k0s[j]) -resApp = approx.errorEstimator(k0s) - -polesApp = approx.getPoles() -polesApp = polesApp[np.abs(np.imag(polesApp)) < 1e-3] -plt.figure() -plt.semilogy(k0s, norm) -plt.semilogy(k0s, normApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(norm)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.semilogy(np.real(polesApp), - 2.*np.max(norm)*np.ones_like(polesApp, dtype = float), 'k.') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, res) -plt.semilogy(k0s, resApp, '--') -plt.semilogy(np.real(approx.mus(0)), - 4.*np.max(resApp)*np.ones(approx.mus.shape, dtype = float), 'rx') -plt.semilogy(np.real(polesApp), - 2.*np.max(resApp)*np.ones_like(polesApp, dtype = float), 'k.') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -plt.figure() -plt.semilogy(k0s, err) -plt.semilogy(np.real(polesApp), - 2.*np.max(err)*np.ones_like(polesApp, dtype = float), 'k.') -plt.xlim([kl, kr]) -plt.grid() -plt.show() -plt.close() - -polesApp = approx.getPoles() -mask = (np.real(polesApp) < kl) | (np.real(polesApp) > kr) -print("Outliers:", polesApp[mask]) -polesApp = polesApp[~mask] -plt.figure() -plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') -plt.axis('equal') -plt.grid() -plt.show() -plt.close() diff --git a/examples/pod/PolesCentered.py b/examples/pod/PolesCentered.py index ab2ee75..02ca328 100644 --- a/examples/pod/PolesCentered.py +++ b/examples/pod/PolesCentered.py @@ -1,74 +1,70 @@ import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzSquareBubbleProblemEngine as HSBPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RB +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.utilities.numerical import squareResonances from rrompy.parameter.parameter_sampling import ManualSampler as MS verb = 0 k0 = (12+0.j) ** .5 krange = [[9. ** .5], [15. ** .5]] Nmin, Nmax = 2, 10 Nvals = np.arange(Nmin, Nmax + 1, 2) -rescaling = lambda x: np.power(x, 2.) -rescalingInv = lambda x: np.power(x, .5) - params = {'N':Nmin, 'M':0, 'S':Nmin + 1, 'POD':True, - 'sampler': MS(krange, points = [k0], scaling = rescaling, - scalingInv = rescalingInv)} + 'sampler': MS(krange, points = [k0], scalingExp = 2.)} #boolCon = lambda x : np.abs(np.imag(x)) < 1e-1 * np.abs(np.real(x) # - np.real(z0)) #cleanupParameters = {'boolCondition':boolCon, 'residueCheck':True} solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 25, verbosity = verb) solver.omega = np.real(k0) approxP = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb) approxR = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) rP, rE = [None] * len(Nvals), [None] * len(Nvals) verbose = 1 for j, N in enumerate(Nvals): if verbose > 0: print('N = E = {}'.format(N)) approxP.approxParameters = {'N':N, 'S':N+1} approxR.approxParameters = {'R':N, 'S':N+1} if verbose > 1: print(approxP.approxParameters) print(approxR.approxParameters) rP[j] = approxP.getPoles() rE[j] = approxR.getPoles() if verbose > 2: print(rP) print(rE) from matplotlib import pyplot as plt plotRows = int(np.ceil(len(Nvals) / 3)) fig, axes = plt.subplots(plotRows, 3, figsize = (15, 3.5 * plotRows)) for j, N in enumerate(Nvals): i1, i2 = int(np.floor(j / 3)), j % 3 axes[i1, i2].set_title('N = E = {}'.format(N)) axes[i1, i2].plot(np.real(rP[j]), np.imag(rP[j]), 'Xb', label="Pade'", markersize = 8) axes[i1, i2].plot(np.real(rE[j]), np.imag(rE[j]), 'Pr', label="RB", markersize = 8) axes[i1, i2].axhline(linewidth=1, color='k') xmin, xmax = axes[i1, i2].get_xlim() height = (xmax - xmin) / 2. res = np.power(squareResonances(xmin**2., xmax**2., False), .5) axes[i1, i2].plot(res, np.zeros_like(res), 'ok', markersize = 4) axes[i1, i2].plot(np.real(k0), np.imag(k0), 'om', markersize = 5) axes[i1, i2].plot(np.real(k0) * np.ones(2), 1.5 * height * np.arange(-1, 3, 2), '--m') axes[i1, i2].grid() axes[i1, i2].set_xlim(xmin, xmax) axes[i1, i2].set_ylim(- height, height) p = axes[i1, i2].legend() plt.tight_layout() for j in range((len(Nvals) - 1) % 3 + 1, 3): axes[plotRows - 1, j].axis('off') diff --git a/examples/pod/PolesDistributed.py b/examples/pod/PolesDistributed.py index 3298b77..6dd37aa 100644 --- a/examples/pod/PolesDistributed.py +++ b/examples/pod/PolesDistributed.py @@ -1,48 +1,45 @@ from matplotlib import pyplot as plt import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzSquareBubbleProblemEngine as HSBPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI +from rrompy.reduction_methods.standard import RationalInterpolant as RI from rrompy.parameter.parameter_sampling import QuadratureSampler as QS from rrompy.utilities.numerical import squareResonances verb = 0 ks = [1., 46. ** .5] solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 20, verbosity = verb) k0 = np.mean(np.power(ks, 2.)) ** .5 k0 = 3.46104724 solver.omega = np.real(k0) -rescaling = lambda x: np.power(x, 2.) -rescalingInv = lambda x: np.power(x, .5) - nsets = 12 paramsPade = {'S':2, 'POD':True, 'polybasis':"LEGENDRE", - 'sampler':QS(ks, "UNIFORM", rescaling, rescalingInv)} + 'sampler':QS(ks, "UNIFORM", rescaleExp = 2.)} approx = RI(solver, mu0 = k0, approxParameters = paramsPade, verbosity = verb) poles = [None] * nsets samples = [None] * nsets polesexact = np.unique(np.power( squareResonances(ks[0]**2., ks[1]**2., False), .5)) for i in range(1, nsets + 1): print("N = {}".format(4 * i)) approx.approxParameters = {'N': 4 * i, 'M': 4 * i, 'S': 4 * i + 1} approx.setupApprox() poles[i - 1] = approx.getPoles() samples[i - 1] = (approx.mus ** 2.).data for i in range(1, nsets + 1): plt.figure() plt.plot(np.real(poles[i - 1]), np.imag(poles[i - 1]), 'kx') plt.plot(polesexact, np.zeros_like(polesexact), 'm.') plt.plot(np.real(samples[i - 1]), np.imag(samples[i - 1]), 'r*') plt.xlim(ks) plt.ylim((ks[0] - ks[1]) / 2., (ks[1] - ks[0]) / 2.) plt.title("N = {}, Neff = {}".format(4 * i, len(poles[i - 1]))) plt.grid() plt.show() plt.close() diff --git a/examples/pod/RationalHermiteInterpolant.py b/examples/pod/RationalHermiteInterpolant.py index abbed8f..d62aed4 100644 --- a/examples/pod/RationalHermiteInterpolant.py +++ b/examples/pod/RationalHermiteInterpolant.py @@ -1,139 +1,133 @@ import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzSquareBubbleProblemEngine as HSBPE from rrompy.hfengines.linear_problem import \ HelmholtzSquareTransmissionProblemEngine as HSTPE from rrompy.hfengines.linear_problem import \ HelmholtzBoxScatteringProblemEngine as HBSPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI +from rrompy.reduction_methods.standard import RationalInterpolant as RI from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, ManualSampler as MS) testNo = 3 verb = 100 polyBasis = "CHEBYSHEV" #polyBasis = "LEGENDRE" #polyBasis = "MONOMIAL" rep = "REPEAT" #rep = "TILE" homog = True #homog = False if testNo == 1: k0s = np.power([10 + 0.j, 14 + 0.j], .5) k0 = np.mean(np.power(k0s, 2.)) ** .5 - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) - samplerBase = QS(k0s, "CHEBYSHEV", rescaling, rescalingInv) + samplerBase = QS(k0s, "CHEBYSHEV", 2.) S = 8 if rep == "REPEAT": points = np.repeat(samplerBase.generatePoints(2).data, int(np.ceil(S / 2))) else: # if rep == "TILE": points = np.tile(samplerBase.generatePoints(2).data, int(np.ceil(S / 2))) params = {'N':7, 'M':6, 'S':S, 'POD':True, 'polybasis':polyBasis, - 'sampler':MS(k0s, points = points, scaling = rescaling, - scalingInv = rescalingInv)} + 'sampler':MS(k0s, points = points, 2.)} ktar = (11 + .5j) ** .5 solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 40, verbosity = verb) solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.setupApprox() approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) ############ elif testNo == 2: k0s = [3.85 + 0.j, 4.15 + 0.j] k0 = np.mean(k0s) ktar = 4 + 0.j - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) - samplerBase = QS(k0s, "CHEBYSHEV", rescaling, rescalingInv) + samplerBase = QS(k0s, "CHEBYSHEV", 2.) S = 10 if rep == "REPEAT": points = np.repeat(samplerBase.generatePoints(5).data, int(np.ceil(S / 5))) else: # if rep == "TILE": points = np.tile(samplerBase.generatePoints(5).data, int(np.ceil(S / 5))) params = {'N':8, 'M':9, 'S':S, 'POD':True, 'polybasis':polyBasis, - 'sampler':MS(k0s, points = points, rescale = rescaling, - rescaleInv = rescalingInv)} + 'sampler':MS(k0s, points = points, 2.)} solver = HSTPE(nT = 2, nB = 1, theta = np.pi * 45/180, kappa = 4., n = 50, verbosity = verb) solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) ############ elif testNo == 3: k0s = [2., 5.] k0 = np.mean(k0s) ktar = 4.5 - 0.j samplerBase = QS(k0s, "CHEBYSHEV") S = 15 if rep == "REPEAT": points = np.repeat(samplerBase.generatePoints(5).data, int(np.ceil(S / 5))) else: # if rep == "TILE": points = np.tile(samplerBase.generatePoints(5).data, int(np.ceil(S / 5))) params = {'N':14, 'M':14, 'S':S, 'POD':True, 'polybasis':polyBasis, 'sampler':MS(k0s, points = points)} solver = HBSPE(R = 7, kappa = 3, theta = - np.pi * 75 / 180, n = 40, verbosity = verb) solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) diff --git a/examples/pod/RationalInterpolant.py b/examples/pod/RationalInterpolant.py index 397ee94..51f7069 100644 --- a/examples/pod/RationalInterpolant.py +++ b/examples/pod/RationalInterpolant.py @@ -1,125 +1,121 @@ import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzSquareBubbleProblemEngine as HSBPE from rrompy.hfengines.linear_problem import \ HelmholtzSquareTransmissionProblemEngine as HSTPE from rrompy.hfengines.linear_problem import \ HelmholtzBoxScatteringProblemEngine as HBSPE -from rrompy.reduction_methods.distributed import RationalInterpolant as RI +from rrompy.reduction_methods.standard import RationalInterpolant as RI from rrompy.parameter.parameter_sampling import QuadratureSampler as QS testNo = 3 verb = 100 polyBasis = "CHEBYSHEV" polyBasis = "LEGENDRE" #polyBasis = "MONOMIAL" homog = True #homog = False loadName = "RationalInterpolantModel.pkl" if testNo in [1, -1]: if testNo > 0: k0s = np.power([10 + 0.j, 14 + 0.j], .5) k0 = np.mean(np.power(k0s, 2.)) ** .5 - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) params = {'N':4, 'M':3, 'S':5, 'POD':True, 'polybasis':polyBasis, - 'sampler':QS(k0s, "CHEBYSHEV", rescaling, rescalingInv)} + 'sampler':QS(k0s, "CHEBYSHEV", 2.)} ktar = (11 + .5j) ** .5 solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 40, verbosity = verb) if testNo > 0: solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.setupApprox() # approx.plotSamples() else: approx = RI(solver, mu0 = 0, approxParameters = {'S':1, 'muBounds':[0, 1]}, verbosity = verb) approx.loadTrainedModel(loadName) approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) if testNo > 0: approx.storeTrainedModel("RationalInterpolantModel", forceNewFile = False) print(approx.trainedModel.data.__dict__) ############ elif testNo == 2: k0s = [3.85 + 0.j, 4.15 + 0.j] k0 = np.mean(k0s) ktar = 4 + 0.j - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) params = {'N':8, 'M':9, 'S':10, 'POD':True, 'polybasis':polyBasis, - 'sampler':QS(k0s, "CHEBYSHEV", rescaling, rescalingInv)} + 'sampler':QS(k0s, "CHEBYSHEV", 2.)} solver = HSTPE(nT = 2, nB = 1, theta = np.pi * 45/180, kappa = 4., n = 50, verbosity = verb) solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) ############ elif testNo == 3: k0s = [2., 5.] k0 = np.mean(k0s) ktar = 4.5 - 0.j params = {'N':10, 'M':9, 'S':15, 'POD':True, 'polybasis':polyBasis, 'sampler':QS(k0s, "CHEBYSHEV")} solver = HBSPE(R = 7, kappa = 3, theta = - np.pi * 75 / 180, n = 40, verbosity = verb) solver.omega = np.real(k0) approx = RI(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_Pade''') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) print('\nPoles Pade'':') print(approx.getPoles()) diff --git a/examples/pod/RBDistributed.py b/examples/pod/ReducedBasis.py similarity index 88% rename from examples/pod/RBDistributed.py rename to examples/pod/ReducedBasis.py index 606cfe2..f48f6bd 100644 --- a/examples/pod/RBDistributed.py +++ b/examples/pod/ReducedBasis.py @@ -1,112 +1,108 @@ import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzSquareBubbleProblemEngine as HSBPE from rrompy.hfengines.linear_problem import \ HelmholtzSquareTransmissionProblemEngine as HSTPE from rrompy.hfengines.linear_problem import \ HelmholtzBoxScatteringProblemEngine as HBSPE -from rrompy.reduction_methods.distributed import RBDistributed as RB +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS testNo = 1 verb = 100 homog = True #homog = False -loadName = "RBDistributedModel.pkl" +loadName = "ReducedBasisModel.pkl" if testNo in [1, -1]: if testNo > 0: k0s = np.power([10 + 0.j, 14 + 0.j], .5) k0 = np.mean(np.power(k0s, 2.)) ** .5 - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) params = {'S':5, 'R':4, 'POD':True, - 'sampler':QS(k0s, "CHEBYSHEV", rescaling, rescalingInv)} + 'sampler':QS(k0s, "CHEBYSHEV", 2.)} ktar = (11 + .5j) ** .5 solver = HSBPE(kappa = 12 ** .5, theta = np.pi / 3, n = 40, verbosity = verb) if testNo > 0: approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb) approx.setupApprox() # approx.plotSamples() else: approx = RB(solver, mu0 = 0, approxParameters = {'S':1, 'muBounds':[0, 1]}, verbosity = verb) approx.loadTrainedModel(loadName) approx.plotApprox(ktar, name = 'u_RB') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) if testNo > 0: - approx.storeTrainedModel("RBDistributedModel", forceNewFile = False) + approx.storeTrainedModel("ReducedBasisModel", forceNewFile = False) print(approx.trainedModel.data.__dict__) ############ elif testNo == 2: k0s = [3.85 + 0.j, 4.15 + 0.j] k0 = np.mean(k0s) ktar = 4 + .15j - rescaling = lambda x: np.power(x, 2.) - rescalingInv = lambda x: np.power(x, .5) params = {'S':10, 'R':9, 'POD':True, - 'sampler':QS(k0s, "CHEBYSHEV", rescaling, rescalingInv)} + 'sampler':QS(k0s, "CHEBYSHEV", 2.)} solver = HSTPE(nT = 2, nB = 1, theta = np.pi * 45/180, kappa = 4., n = 50, verbosity = verb) solver.omega = np.real(k0) approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_RB') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) ############ elif testNo == 3: k0s = [2., 5.] k0 = np.mean(k0s) ktar = 4.5 - 0.j params = {'S':15, 'R':10, 'POD':True, 'sampler':QS(k0s, "CHEBYSHEV")} solver = HBSPE(R = 7, kappa = 3, theta = - np.pi * 75 / 180, n = 40, verbosity = verb) solver.omega = np.real(k0) approx = RB(solver, mu0 = k0, approxParameters = params, verbosity = verb, homogeneized = homog) approx.setupApprox() # approx.plotSamples() approx.plotApprox(ktar, name = 'u_RB') approx.plotHF(ktar, name = 'u_HF') approx.plotErr(ktar, name = 'err') approx.plotRes(ktar, name = 'res') appErr, solNorm = approx.normErr(ktar), approx.normHF(ktar) resNorm, RHSNorm = approx.normRes(ktar), approx.normRHS(ktar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) diff --git a/examples/pod/matrix_pod.py b/examples/pod/matrix_pod.py index cc3f90b..8fbd742 100644 --- a/examples/pod/matrix_pod.py +++ b/examples/pod/matrix_pod.py @@ -1,68 +1,68 @@ import numpy as np import scipy.sparse as sp from matplotlib import pyplot as plt from rrompy.hfengines.base import MatrixEngineBase as MEB -from rrompy.reduction_methods.distributed import RationalInterpolant as RI -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as RI +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS test = 2 method = "RationalInterpolant" -#method = "RBDistributed" +#method = "ReducedBasis" verb = 0 N = 100 solver = MEB(verbosity = verb) solver.npar = 1 solver.nAs = 2 if test == 1: solver.As = [sp.spdiags([np.arange(1, 1 + N)], [0], N, N), - sp.eye(N)] elif test == 2: solver.setSolver("SOLVE") fftB = np.fft.fft(np.eye(N)) * N**-.5 solver.As = [fftB.dot(np.multiply(np.arange(1, 1 + N), fftB.conj()).T), - np.eye(N)] np.random.seed(420) solver.nbs = 1 solver.bs = [np.random.randn(N) + 1.j * np.random.randn(N)] mu0 = 10.25 mutar = 12.5 murange = [5.25, 15.25] if method == "RationalInterpolant": params = {'N':10, 'M':9, 'S':11, 'POD':True, 'polybasis':"CHEBYSHEV", 'sampler':QS(murange, "CHEBYSHEV")} approx = RI(solver, mu0 = mu0, approxParameters = params, verbosity = verb) -elif method == "RBDistributed": +elif method == "ReducedBasis": params = {'R':10, 'S':11, 'POD':True, 'sampler':QS(murange, "CHEBYSHEV")} - approx = RBD(solver, mu0 = mu0, approxParameters = params, - verbosity = verb) + approx = RB(solver, mu0 = mu0, approxParameters = params, + verbosity = verb) approx.setupApprox() approx.plotApprox(mutar, name = 'u_app') approx.plotHF(mutar, name = 'u_HF') approx.plotErr(mutar, name = 'err') approx.plotRes(mutar, name = 'res') appErr, solNorm = approx.normErr(mutar), approx.normHF(mutar) resNorm, RHSNorm = approx.normRes(mutar), approx.normRHS(mutar) print(('SolNorm:\t{}\nErr:\t{}\nErrRel:\t{}').format(solNorm, appErr, np.divide(appErr, solNorm))) print(('RHSNorm:\t{}\nRes:\t{}\nResRel:\t{}').format(RHSNorm, resNorm, np.divide(resNorm, RHSNorm))) polesTrue = np.arange(1, 1 + N) polesTrue = polesTrue[polesTrue >= murange[0]] polesTrue = polesTrue[polesTrue <= murange[1]] polesApp = approx.getPoles() mask = (np.real(polesApp) < murange[0]) | (np.real(polesApp) > murange[1]) print("Outliers:", polesApp[mask]) polesApp = polesApp[~mask] plt.figure() plt.plot(np.real(polesApp), np.imag(polesApp), 'kx') plt.plot(polesTrue, np.zeros_like(polesTrue), 'm.') plt.axis('equal') plt.grid() plt.show() plt.close() diff --git a/examples/pod/scatteringSquare.py b/examples/pod/scatteringSquare.py index d313958..163f778 100644 --- a/examples/pod/scatteringSquare.py +++ b/examples/pod/scatteringSquare.py @@ -1,73 +1,72 @@ import numpy as np from rrompy.hfengines.linear_problem import \ HelmholtzCavityScatteringProblemEngine as CSPE -from rrompy.reduction_methods.distributed import RationalInterpolant as PD -from rrompy.reduction_methods.distributed import RBDistributed as RBD +from rrompy.reduction_methods.standard import RationalInterpolant as PD +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import QuadratureSampler as QS from operator import itemgetter def subdict(d, ks): return dict(zip(ks, itemgetter(*ks)(d))) verb = 0 #################### test = "solve" -#test = "Distributed" +#test = "approx" plotSamples = True k0 = 10 kLeft, kRight = 9, 11 ktar = 9.5 ktars = np.linspace(8.5, 11.5, 125) #ktars = np.array([k0]) kappa = 5 n = 50 solver = CSPE(kappa = kappa, n = n, verbosity = verb) solver.omega = k0 if test == "solve": uh = solver.solve(k0)[0] print(solver.norm(uh)) solver.plot(uh, what = ['ABS', 'REAL']) -elif test == "Distributed": +elif test == "approx": params = {'N':8, 'M':8, 'R':9, 'S':9, 'POD':True, 'polybasis':"CHEBYSHEV", 'sampler':QS([kLeft, kRight], "CHEBYSHEV")} parPade = subdict(params, ['N', 'M', 'S', 'POD', 'polybasis', 'sampler']) parRB = subdict(params, ['R', 'S', 'POD', 'sampler']) approxPade = PD(solver, mu0 = np.mean([kLeft, kRight]), approxParameters = parPade, verbosity = verb) - approxRB = RBD(solver, mu0 = np.mean([kLeft, kRight]), - approxParameters = parRB, - verbosity = verb) + approxRB = RB(solver, mu0 = np.mean([kLeft, kRight]), + approxParameters = parRB, verbosity = verb) approxPade.setupApprox() approxRB.setupApprox() if plotSamples: approxPade.plotSamples() PadeErr, solNorm = approxPade.normErr(ktar), approxPade.normHF(ktar) RBErr = approxRB.normErr(ktar) print(('SolNorm:\t{}\nErrPade:\t{}\nErrRelPade:\t{}\nErrRB:\t\t{}' '\nErrRelRB:\t{}').format(solNorm, PadeErr, np.divide(PadeErr, solNorm), RBErr, np.divide(RBErr, solNorm))) print('\nPoles Pade'':') print(approxPade.getPoles()) print('\nPoles RB:') print(approxRB.getPoles()) approxPade.plotHF(ktar, name = 'u_ex') approxPade.plotApprox(ktar, name = 'u_Pade''') approxRB.plotApprox(ktar, name = 'u_RB') approxPade.plotErr(ktar, name = 'errPade''') approxRB.plotErr(ktar, name = 'errRB') diff --git a/rrompy/reduction_methods/distributed_greedy/__init__.py b/rrompy/reduction_methods/greedy/__init__.py similarity index 83% rename from rrompy/reduction_methods/distributed_greedy/__init__.py rename to rrompy/reduction_methods/greedy/__init__.py index ccdf783..623f762 100644 --- a/rrompy/reduction_methods/distributed_greedy/__init__.py +++ b/rrompy/reduction_methods/greedy/__init__.py @@ -1,30 +1,29 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # -from .generic_distributed_greedy_approximant import \ - GenericDistributedGreedyApproximant +from .generic_greedy_approximant import GenericGreedyApproximant from .rational_interpolant_greedy import RationalInterpolantGreedy from .reduced_basis_greedy import ReducedBasisGreedy __all__ = [ - 'GenericDistributedGreedyApproximant', + 'GenericGreedyApproximant', 'RationalInterpolantGreedy', 'ReducedBasisGreedy' ] diff --git a/rrompy/reduction_methods/distributed_greedy/generic_distributed_greedy_approximant.py b/rrompy/reduction_methods/greedy/generic_greedy_approximant.py similarity index 98% rename from rrompy/reduction_methods/distributed_greedy/generic_distributed_greedy_approximant.py rename to rrompy/reduction_methods/greedy/generic_greedy_approximant.py index d1ae9f5..c0f41fa 100644 --- a/rrompy/reduction_methods/distributed_greedy/generic_distributed_greedy_approximant.py +++ b/rrompy/reduction_methods/greedy/generic_greedy_approximant.py @@ -1,583 +1,583 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np -from rrompy.reduction_methods.distributed.generic_distributed_approximant \ - import GenericDistributedApproximant +from rrompy.reduction_methods.standard.generic_standard_approximant \ + import GenericStandardApproximant from rrompy.utilities.base.types import (Np1D, Np2D, DictAny, HFEng, Tuple, List, normEng, paramVal, paramList, sampList) from rrompy.utilities.base import verbosityManager as vbMng from rrompy.solver import normEngine from rrompy.utilities.exception_manager import (RROMPyException, RROMPyAssert, RROMPyWarning) from rrompy.parameter import checkParameterList, emptyParameterList -__all__ = ['GenericDistributedGreedyApproximant'] +__all__ = ['GenericGreedyApproximant'] def pruneSamples(mus:paramList, badmus:paramList, tol : float = 1e-8) -> paramList: """Remove from mus all the elements which are too close to badmus.""" if len(badmus) == 0: return mus musNp = np.array(mus(0)) badmus = np.array(badmus(0)) proximity = np.min(np.abs(musNp.reshape(-1, 1) - np.tile(badmus.reshape(1, -1), [len(mus), 1])), axis = 1).flatten() idxPop = np.arange(len(mus))[proximity <= tol] for i, j in enumerate(idxPop): mus.pop(j - i) return mus -class GenericDistributedGreedyApproximant(GenericDistributedApproximant): +class GenericGreedyApproximant(GenericStandardApproximant): """ ROM greedy interpolant computation for parametric problems (ABSTRACT). Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': number of starting training points; - 'sampler': sample point generator; - 'greedyTol': uniform error tolerance for greedy algorithm; defaults to 1e-2; - 'interactive': whether to interactively terminate greedy algorithm; defaults to False; - 'maxIter': maximum number of greedy steps; defaults to 1e2; - 'refinementRatio': ratio of test points to be exhausted before test set refinement; defaults to 0.2; - 'nTestPoints': number of test points; defaults to 5e2; - 'trainSetGenerator': training sample points generator; defaults to sampler. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots. - 'greedyTol': uniform error tolerance for greedy algorithm; - 'interactive': whether to interactively terminate greedy algorithm; - 'maxIter': maximum number of greedy steps; - 'refinementRatio': ratio of test points to be exhausted before test set refinement; - 'nTestPoints': number of test points; - 'trainSetGenerator': training sample points generator. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. POD: whether to compute POD of snapshots. S: number of test points. sampler: Sample point generator. greedyTol: uniform error tolerance for greedy algorithm. interactive: whether to interactively terminate greedy algorithm. maxIter: maximum number of greedy steps. refinementRatio: ratio of training points to be exhausted before training set refinement. nTestPoints: number of starting training points. trainSetGenerator: training sample points generator. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. estimatorNormEngine: Engine for estimator norm computation. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. """ TOL_INSTABILITY = 1e-6 def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList(["greedyTol", "interactive", "maxIter", "refinementRatio", "nTestPoints"], [1e-2, False, 1e2, .2, 5e2], ["trainSetGenerator"], ["AUTO"]) super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) RROMPyAssert(self.HFEngine.npar, 1, "Parameter dimension") self._postInit() @property def greedyTol(self): """Value of greedyTol.""" return self._greedyTol @greedyTol.setter def greedyTol(self, greedyTol): if greedyTol < 0: raise RROMPyException("greedyTol must be non-negative.") if hasattr(self, "_greedyTol") and self.greedyTol is not None: greedyTolold = self.greedyTol else: greedyTolold = -1 self._greedyTol = greedyTol self._approxParameters["greedyTol"] = self.greedyTol if greedyTolold != self.greedyTol: self.resetSamples() @property def interactive(self): """Value of interactive.""" return self._interactive @interactive.setter def interactive(self, interactive): self._interactive = interactive @property def maxIter(self): """Value of maxIter.""" return self._maxIter @maxIter.setter def maxIter(self, maxIter): if maxIter <= 0: raise RROMPyException("maxIter must be positive.") if hasattr(self, "_maxIter") and self.maxIter is not None: maxIterold = self.maxIter else: maxIterold = -1 self._maxIter = maxIter self._approxParameters["maxIter"] = self.maxIter if maxIterold != self.maxIter: self.resetSamples() @property def refinementRatio(self): """Value of refinementRatio.""" return self._refinementRatio @refinementRatio.setter def refinementRatio(self, refinementRatio): if refinementRatio <= 0. or refinementRatio > 1.: raise RROMPyException(("refinementRatio must be between 0 " "(excluded) and 1.")) if (hasattr(self, "_refinementRatio") and self.refinementRatio is not None): refinementRatioold = self.refinementRatio else: refinementRatioold = -1 self._refinementRatio = refinementRatio self._approxParameters["refinementRatio"] = self.refinementRatio if refinementRatioold != self.refinementRatio: self.resetSamples() @property def nTestPoints(self): """Value of nTestPoints.""" return self._nTestPoints @nTestPoints.setter def nTestPoints(self, nTestPoints): if nTestPoints <= 0: raise RROMPyException("nTestPoints must be positive.") if not np.isclose(nTestPoints, np.int(nTestPoints)): raise RROMPyException("nTestPoints must be an integer.") nTestPoints = np.int(nTestPoints) if hasattr(self, "_nTestPoints") and self.nTestPoints is not None: nTestPointsold = self.nTestPoints else: nTestPointsold = -1 self._nTestPoints = nTestPoints self._approxParameters["nTestPoints"] = self.nTestPoints if nTestPointsold != self.nTestPoints: self.resetSamples() @property def trainSetGenerator(self): """Value of trainSetGenerator.""" return self._trainSetGenerator @trainSetGenerator.setter def trainSetGenerator(self, trainSetGenerator): if (isinstance(trainSetGenerator, (str,)) and trainSetGenerator.upper() == "AUTO"): trainSetGenerator = self.sampler if 'generatePoints' not in dir(trainSetGenerator): raise RROMPyException("trainSetGenerator type not recognized.") if (hasattr(self, '_trainSetGenerator') and self.trainSetGenerator not in [None, "AUTO"]): trainSetGeneratorOld = self.trainSetGenerator self._trainSetGenerator = trainSetGenerator self._approxParameters["trainSetGenerator"] = self.trainSetGenerator if (not 'trainSetGeneratorOld' in locals() or trainSetGeneratorOld != self.trainSetGenerator): self.resetSamples() def resetSamples(self): """Reset samples.""" super().resetSamples() self._mus = emptyParameterList() def initEstimatorNormEngine(self, normEngn : normEng = None): """Initialize estimator norm engine.""" if (normEngn is not None or not hasattr(self, "estimatorNormEngine") or self.estimatorNormEngine is None): if normEngn is None: if not hasattr(self.HFEngine, "energyNormPartialDualMatrix"): self.HFEngine.buildEnergyNormPartialDualForm() estimatorEnergyMatrix = ( self.HFEngine.energyNormPartialDualMatrix) else: if hasattr(normEngn, "buildEnergyNormPartialDualForm"): if not hasattr(normEngn, "energyNormPartialDualMatrix"): normEngn.buildEnergyNormPartialDualForm() estimatorEnergyMatrix = ( normEngn.energyNormPartialDualMatrix) else: estimatorEnergyMatrix = normEngn self.estimatorNormEngine = normEngine(estimatorEnergyMatrix) def errorEstimator(self, mus:paramList) -> List[complex]: """ Standard residual-based error estimator with explicit residual computation. """ self.setupApprox() res = self.getRes(mus, homogeneized = self.homogeneized, duality = False) if self.HFEngine.nbs == 1: RHS = self.getRHS(mus[0], homogeneized = self.homogeneized, duality = False) else: RHS = self.getRHS(mus, homogeneized = self.homogeneized, duality = False) return np.abs(self.estimatorNormEngine.norm(res) / self.estimatorNormEngine.norm(RHS)) def getMaxErrorEstimator(self, mus:paramList, plot : bool = False) -> Tuple[Np1D, int, float]: """ Compute maximum of (and index of maximum of) error estimator over given parameters. """ errorEstTest = self.errorEstimator(mus) idxMaxEst = np.argmax(errorEstTest) maxEst = errorEstTest[idxMaxEst] if plot and not np.all(np.isinf(errorEstTest)): musre = mus.re(0) from matplotlib import pyplot as plt plt.figure() plt.semilogy(musre, errorEstTest, 'k') plt.semilogy([musre[0], musre[-1]], [self.greedyTol] * 2, 'r--') plt.semilogy(self.mus.re(0), 2. * self.greedyTol * np.ones(len(self.mus)), '*m') plt.semilogy(musre[idxMaxEst], maxEst, 'xr') plt.grid() plt.show() plt.close() return errorEstTest, idxMaxEst, maxEst def greedyNextSample(self, muidx:int, plotEst : bool = False)\ -> Tuple[Np1D, int, float, paramVal]: """Compute next greedy snapshot of solution map.""" RROMPyAssert(self._mode, message = "Cannot add greedy sample.") mu = copy(self.muTest[muidx]) self.muTest.pop(muidx) vbMng(self, "MAIN", ("Adding {}-th sample point at {} to training " "set.").format(self.samplingEngine.nsamples + 1, mu), 2) self.mus.append(mu) self.samplingEngine.nextSample(mu, homogeneized = self.homogeneized) errorEstTest, muidx, maxErrorEst = self.getMaxErrorEstimator( self.muTest, plotEst) return errorEstTest, muidx, maxErrorEst, self.muTest[muidx] def _preliminaryTraining(self): """Initialize starting snapshots of solution map.""" RROMPyAssert(self._mode, message = "Cannot start greedy algorithm.") self.computeScaleFactor() if self.samplingEngine.nsamples > 0: return vbMng(self, "INIT", "Starting computation of snapshots.", 2) self.resetSamples() self.mus = self.trainSetGenerator.generatePoints(self.S) muTestBase = self.sampler.generatePoints(self.nTestPoints) muTestBase = pruneSamples(muTestBase, self.mus, 1e-10 * self.scaleFactor[0]).sort() muLast = copy(self.mus[-1]) self.mus.pop() if len(self.mus) > 0: nSamples = np.prod(self.S) - 1 vbMng(self, "MAIN", ("Adding first {} sample point{} at {} to training " "set.").format(nSamples, "" + "s" * (nSamples > 1), self.mus), 2) self.samplingEngine.iterSample(self.mus, homogeneized = self.homogeneized) self.muTest = emptyParameterList() self.muTest.reset((len(muTestBase) + 1, self.mus.shape[1])) self.muTest[: -1] = muTestBase self.muTest[-1] = muLast def _enrichTestSet(self, nTest:int): """Add extra elements to test set.""" RROMPyAssert(self._mode, message = "Cannot enrich test set.") muTestExtra = self.sampler.generatePoints(2 * nTest) muTotal = copy(self.mus) muTotal.append(self.muTest) muTestExtra = pruneSamples(muTestExtra, muTotal, 1e-10 * self.scaleFactor[0]) muTestNew = np.empty(len(self.muTest) + len(muTestExtra), dtype = np.complex) muTestNew[: len(self.muTest)] = self.muTest(0) muTestNew[len(self.muTest) :] = muTestExtra(0) self.muTest = checkParameterList(muTestNew.sort(), self.npar)[0] vbMng(self, "MAIN", "Enriching test set by {} elements.".format(len(muTestExtra)), 5) def greedy(self, plotEst : bool = False): """Compute greedy snapshots of solution map.""" RROMPyAssert(self._mode, message = "Cannot start greedy algorithm.") if self.samplingEngine.nsamples > 0: return self._preliminaryTraining() nTest = self.nTestPoints errorEstTest, muidx, maxErrorEst, mu = self.greedyNextSample(-1, plotEst) vbMng(self, "MAIN", "Uniform testing error estimate {:.4e}.".format(maxErrorEst), 2) trainedModelOld = copy(self.trainedModel) while (self.samplingEngine.nsamples < self.maxIter and maxErrorEst > self.greedyTol): if (1. - self.refinementRatio) * nTest > len(self.muTest): self._enrichTestSet(nTest) nTest = len(self.muTest) muTestOld, maxErrorEstOld = self.muTest, maxErrorEst errorEstTest, muidx, maxErrorEst, mu = self.greedyNextSample( muidx, plotEst) vbMng(self, "MAIN", "Uniform testing error estimate {:.4e}.".format(maxErrorEst), 2) if (np.isnan(maxErrorEst) or np.isinf(maxErrorEst) or maxErrorEstOld < maxErrorEst * self.TOL_INSTABILITY): RROMPyWarning(("Instability in a posteriori estimator. " "Starting preemptive greedy loop termination.")) maxErrorEst = maxErrorEstOld self.muTest = muTestOld self.mus = self.mus[:-1] self.samplingEngine.popSample() self.trainedModel.data = copy(trainedModelOld.data) break trainedModelOld.data = copy(self.trainedModel.data) if (self.interactive and maxErrorEst <= self.greedyTol): vbMng(self, "MAIN", ("Required tolerance {} achieved. Want to decrease " "greedyTol and continue? Y/N").format(self.greedyTol), 0, end = "") increasemaxIter = input() if increasemaxIter.upper() == "Y": vbMng(self, "MAIN", "Reducing value of greedyTol...", 0) while maxErrorEst <= self._greedyTol: self._greedyTol *= .5 if (self.interactive and self.samplingEngine.nsamples >= self.maxIter): vbMng(self, "MAIN", ("Maximum number of iterations {} reached. Want to " "increase maxIter and continue? " "Y/N").format(self.maxIter), 0, end = "") increasemaxIter = input() if increasemaxIter.upper() == "Y": vbMng(self, "MAIN", "Doubling value of maxIter...", 0) self._maxIter *= 2 vbMng(self, "DEL", ("Done computing snapshots (final snapshot count: " "{}).").format(self.samplingEngine.nsamples), 2) def checkComputedApprox(self) -> bool: """ Check if setup of new approximant is not needed. Returns: True if new setup is not needed. False otherwise. """ return (super().checkComputedApprox() and len(self.mus) == self.trainedModel.data.projMat.shape[1]) def assembleReducedResidualGramian(self, pMat:sampList): """ Build residual gramian of reduced linear system through projections. """ self.initEstimatorNormEngine() if (not hasattr(self.trainedModel.data, "gramian") or self.trainedModel.data.gramian is None): gramian = self.estimatorNormEngine.innerProduct(pMat, pMat) else: Sold = self.trainedModel.data.gramian.shape[0] S = len(self.mus) if Sold > S: gramian = self.trainedModel.data.gramian[: S, : S] else: idxOld = list(range(Sold)) idxNew = list(range(Sold, S)) gramian = np.empty((S, S), dtype = np.complex) gramian[: Sold, : Sold] = self.trainedModel.data.gramian gramian[: Sold, Sold :] = ( self.estimatorNormEngine.innerProduct(pMat(idxNew), pMat(idxOld))) gramian[Sold :, : Sold] = gramian[: Sold, Sold :].T.conj() gramian[Sold :, Sold :] = ( self.estimatorNormEngine.innerProduct(pMat(idxNew), pMat(idxNew))) self.trainedModel.data.gramian = gramian def assembleReducedResidualBlocksbb(self, bs:List[Np1D]): """ Build blocks (of type bb) of reduced linear system through projections. """ self.initEstimatorNormEngine() nbs = len(bs) if (not hasattr(self.trainedModel.data, "resbb") or self.trainedModel.data.resbb is None): resbb = np.empty((nbs, nbs), dtype = np.complex) for i in range(nbs): Mbi = bs[i] resbb[i, i] = self.estimatorNormEngine.innerProduct(Mbi, Mbi) for j in range(i): Mbj = bs[j] resbb[i, j] = self.estimatorNormEngine.innerProduct(Mbj, Mbi) for i in range(nbs): for j in range(i + 1, nbs): resbb[i, j] = resbb[j, i].conj() self.trainedModel.data.resbb = resbb def assembleReducedResidualBlocksAb(self, As:List[Np2D], bs:List[Np1D], pMat:sampList): """ Build blocks (of type Ab) of reduced linear system through projections. """ self.initEstimatorNormEngine() nAs = len(As) nbs = len(bs) S = len(self.mus) if (not hasattr(self.trainedModel.data, "resAb") or self.trainedModel.data.resAb is None): if not isinstance(pMat, (np.ndarray,)): pMat = pMat.data resAb = np.empty((nbs, S, nAs), dtype = np.complex) for j in range(nAs): MAj = As[j].dot(pMat) for i in range(nbs): Mbi = bs[i] resAb[i, :, j] = self.estimatorNormEngine.innerProduct(MAj, Mbi) else: Sold = self.trainedModel.data.resAb.shape[1] if Sold == S: return if Sold > S: resAb = self.trainedModel.data.resAb[:, : S, :] else: if not isinstance(pMat, (np.ndarray,)): pMat = pMat.data resAb = np.empty((nbs, S, nAs), dtype = np.complex) resAb[:, : Sold, :] = self.trainedModel.data.resAb for j in range(nAs): MAj = As[j].dot(pMat[:, Sold :]) for i in range(nbs): Mbi = bs[i] resAb[i, Sold :, j] = ( self.estimatorNormEngine.innerProduct(MAj, Mbi)) self.trainedModel.data.resAb = resAb def assembleReducedResidualBlocksAA(self, As:List[Np2D], pMat:sampList): """ Build blocks (of type AA) of reduced linear system through projections. """ self.initEstimatorNormEngine() nAs = len(As) S = len(self.mus) if (not hasattr(self.trainedModel.data, "resAA") or self.trainedModel.data.resAA is None): if not isinstance(pMat, (np.ndarray,)): pMat = pMat.data resAA = np.empty((S, nAs, S, nAs), dtype = np.complex) for i in range(nAs): MAi = As[i].dot(pMat) resAA[:, i, :, i] = ( self.estimatorNormEngine.innerProduct(MAi, MAi)) for j in range(i): MAj = As[j].dot(pMat) resAA[:, i, :, j] = ( self.estimatorNormEngine.innerProduct(MAj, MAi)) for i in range(nAs): for j in range(i + 1, nAs): resAA[:, i, :, j] = resAA[:, j, :, i].T.conj() else: Sold = self.trainedModel.data.resAA.shape[0] if Sold == S: return if Sold > S: resAA = self.trainedModel.data.resAA[: S, :, : S, :] else: if not isinstance(pMat, (np.ndarray,)): pMat = pMat.data resAA = np.empty((S, nAs, S, nAs), dtype = np.complex) resAA[: Sold, :, : Sold, :] = self.trainedModel.data.resAA for i in range(nAs): MAi = As[i].dot(pMat) resAA[: Sold, i, Sold :, i] = ( self.estimatorNormEngine.innerProduct(MAi[:, Sold :], MAi[:, : Sold])) resAA[Sold :, i, : Sold, i] = resAA[: Sold, i, Sold :, i].T.conj() resAA[Sold :, i, Sold :, i] = ( self.estimatorNormEngine.innerProduct(MAi[:, Sold :], MAi[:, Sold :])) for j in range(i): MAj = As[j].dot(pMat) resAA[: Sold, i, Sold :, j] = ( self.estimatorNormEngine.innerProduct(MAj[:, Sold :], MAi[:, : Sold])) resAA[Sold :, i, : Sold, j] = ( self.estimatorNormEngine.innerProduct(MAj[:, : Sold], MAi[:, Sold :])) resAA[Sold :, i, Sold :, j] = ( self.estimatorNormEngine.innerProduct(MAj[:, Sold :], MAi[:, Sold :])) for i in range(nAs): for j in range(i + 1, nAs): resAA[: Sold, i, Sold :, j] = ( resAA[Sold :, j, : Sold, i].T.conj()) resAA[Sold :, i, : Sold, j] = ( resAA[: Sold, j, Sold :, i].T.conj()) resAA[Sold :, i, Sold :, j] = ( resAA[Sold :, j, Sold :, i].T.conj()) self.trainedModel.data.resAA = resAA def assembleReducedResidualBlocks(self, full : bool = False): """Build affine blocks of affine decomposition of residual.""" self.assembleReducedResidualBlocksbb(self.bs) if full: pMat = self.trainedModel.data.projMat self.assembleReducedResidualBlocksAb(self.As, self.bs, pMat) self.assembleReducedResidualBlocksAA(self.As, pMat) diff --git a/rrompy/reduction_methods/distributed_greedy/rational_interpolant_greedy.py b/rrompy/reduction_methods/greedy/rational_interpolant_greedy.py similarity index 98% rename from rrompy/reduction_methods/distributed_greedy/rational_interpolant_greedy.py rename to rrompy/reduction_methods/greedy/rational_interpolant_greedy.py index 661bade..4ff7253 100644 --- a/rrompy/reduction_methods/distributed_greedy/rational_interpolant_greedy.py +++ b/rrompy/reduction_methods/greedy/rational_interpolant_greedy.py @@ -1,355 +1,353 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np -from .generic_distributed_greedy_approximant import \ - GenericDistributedGreedyApproximant +from .generic_greedy_approximant import GenericGreedyApproximant from rrompy.utilities.poly_fitting.polynomial import (polybases, polydomcoeff, PolynomialInterpolator as PI) -from rrompy.reduction_methods.distributed import RationalInterpolant +from rrompy.reduction_methods.standard import RationalInterpolant from rrompy.reduction_methods.trained_model import ( TrainedModelRational as tModel) from rrompy.reduction_methods.trained_model import TrainedModelData from rrompy.utilities.base.types import Np1D, Np2D, DictAny, HFEng, paramVal from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import RROMPyWarning from rrompy.utilities.exception_manager import RROMPyException, RROMPyAssert __all__ = ['RationalInterpolantGreedy'] -class RationalInterpolantGreedy(GenericDistributedGreedyApproximant, - RationalInterpolant): +class RationalInterpolantGreedy(GenericGreedyApproximant, RationalInterpolant): """ ROM greedy rational interpolant computation for parametric problems. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': number of starting training points; - 'sampler': sample point generator; - 'radialBasis': radial basis family for interpolant numerator; defaults to 0, i.e. no radial basis; - 'radialBasisWeights': radial basis weights for interpolant numerator; defaults to 0, i.e. identity; - 'greedyTol': uniform error tolerance for greedy algorithm; defaults to 1e-2; - 'interactive': whether to interactively terminate greedy algorithm; defaults to False; - 'maxIter': maximum number of greedy steps; defaults to 1e2; - 'refinementRatio': ratio of training points to be exhausted before training set refinement; defaults to 0.2; - 'nTestPoints': number of test points; defaults to 5e2; - 'trainSetGenerator': training sample points generator; defaults to sampler; - 'polybasis': type of basis for interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'errorEstimatorKind': kind of error estimator; available values include 'EXACT', 'BASIC', and 'BARE'; defaults to 'EXACT'; - 'interpRcond': tolerance for interpolation; defaults to None; - 'robustTol': tolerance for robust rational denominator management; defaults to 0. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots. - 'radialBasis': radial basis family for interpolant numerator; defaults to 0, i.e. no radial basis; - 'radialBasisWeights': radial basis weights for interpolant numerator; defaults to 0, i.e. identity; - 'greedyTol': uniform error tolerance for greedy algorithm; - 'interactive': whether to interactively terminate greedy algorithm; - 'maxIter': maximum number of greedy steps; - 'refinementRatio': ratio of test points to be exhausted before test set refinement; - 'nTestPoints': number of test points; - 'trainSetGenerator': training sample points generator; - 'errorEstimatorKind': kind of error estimator; - 'interpRcond': tolerance for interpolation; - 'robustTol': tolerance for robust rational denominator management. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. POD: whether to compute POD of snapshots. S: number of test points. sampler: Sample point generator. radialBasis: Radial basis family for interpolant numerator. radialBasisWeights: Radial basis weights for interpolant numerator. greedyTol: uniform error tolerance for greedy algorithm. interactive: whether to interactively terminate greedy algorithm. maxIter: maximum number of greedy steps. refinementRatio: ratio of training points to be exhausted before training set refinement. nTestPoints: number of starting training points. trainSetGenerator: training sample points generator. robustTol: tolerance for robust rational denominator management. errorEstimatorKind: kind of error estimator. interpRcond: tolerance for interpolation. robustTol: tolerance for robust rational denominator management. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. estimatorNormEngine: Engine for estimator norm computation. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. """ _allowedEstimatorKinds = ["EXACT", "BASIC", "BARE"] def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList(["polybasis", "errorEstimatorKind", "interpRcond", "robustTol"], ["MONOMIAL", "EXACT", -1, 0], toBeExcluded = ["E"]) super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self._postInit() @property def E(self): """Value of E.""" self._E = np.prod(self._S) - 1 return self._E @E.setter def E(self, E): RROMPyWarning(("E is used just to simplify inheritance, and its value " "cannot be changed from that of prod(S) - 1.")) @property def polybasis(self): """Value of polybasis.""" return self._polybasis @polybasis.setter def polybasis(self, polybasis): try: polybasis = polybasis.upper().strip().replace(" ","") if polybasis not in polybases: raise RROMPyException("Sample type not recognized.") self._polybasis = polybasis except: RROMPyWarning(("Prescribed polybasis not recognized. Overriding " "to 'MONOMIAL'.")) self._polybasis = "MONOMIAL" self._approxParameters["polybasis"] = self.polybasis @property def errorEstimatorKind(self): """Value of errorEstimatorKind.""" return self._errorEstimatorKind @errorEstimatorKind.setter def errorEstimatorKind(self, errorEstimatorKind): errorEstimatorKind = errorEstimatorKind.upper() if errorEstimatorKind not in self._allowedEstimatorKinds: RROMPyWarning(("Error estimator kind not recognized. Overriding " "to 'EXACT'.")) errorEstimatorKind = "EXACT" self._errorEstimatorKind = errorEstimatorKind self._approxParameters["errorEstimatorKind"] = self.errorEstimatorKind @property def nTestPoints(self): """Value of nTestPoints.""" return self._nTestPoints @nTestPoints.setter def nTestPoints(self, nTestPoints): if nTestPoints <= 0: RROMPyWarning("nTestPoints must be at least 1. Overriding to 1.") nTestPoints = 1 if not np.isclose(nTestPoints, np.int(nTestPoints)): raise RROMPyException("nTestPoints must be an integer.") nTestPoints = np.int(nTestPoints) if hasattr(self, "_nTestPoints") and self.nTestPoints is not None: nTestPointsold = self.nTestPoints else: nTestPointsold = -1 self._nTestPoints = nTestPoints self._approxParameters["nTestPoints"] = self.nTestPoints if nTestPointsold != self.nTestPoints: self.resetSamples() def _errorSamplingRatio(self, mus:Np1D, muRTest:Np1D, muRTrain:Np1D) -> Np1D: """Scalar ratio in explicit error estimator.""" self.setupApprox() testTile = np.tile(np.reshape(muRTest, (-1, 1)), [1, len(muRTrain)]) nodalVals = np.prod(testTile - np.reshape(muRTrain, (1, -1)), axis = 1) denVals = self.trainedModel.getQVal(mus) return np.abs(nodalVals / denVals) def _RHSNorms(self, radiusb0:Np2D) -> Np1D: """High fidelity system RHS norms.""" self.assembleReducedResidualBlocks(full = False) # 'ij,jk,ik->k', resbb, radiusb0, radiusb0.conj() b0resb0 = np.sum(self.trainedModel.data.resbb.dot(radiusb0) * radiusb0.conj(), axis = 0) RHSnorms = np.power(np.abs(b0resb0), .5) return RHSnorms def _errorEstimatorBare(self) -> Np1D: """Bare residual-based error estimator.""" self.setupApprox() self.assembleReducedResidualGramian(self.trainedModel.data.projMat) pDom = self.trainedModel.data.P.domCoeff LL = pDom.conj().dot(self.trainedModel.data.gramian.dot(pDom)) Adiag = self.As[0].diagonal() AnormApprox = np.linalg.norm(Adiag) ** 2. / np.size(Adiag) return np.abs(AnormApprox * LL) ** .5 def _errorEstimatorBasic(self, muTest:paramVal, ratioTest:complex) -> Np1D: """Basic residual-based error estimator.""" resmu = self.HFEngine.residual(self.getApprox(muTest), muTest, self.homogeneized, duality = False)[0] return np.abs(self.estimatorNormEngine.norm(resmu) / ratioTest) def _errorEstimatorExact(self, muRTrain:Np1D, vanderBase:Np2D) -> Np1D: """Exact residual-based error estimator.""" self.setupApprox() self.assembleReducedResidualBlocks(full = True) nAsM = self.HFEngine.nAs - 1 nbsM = max(self.HFEngine.nbs - 1, nAsM * self.homogeneized) radiusA = np.zeros((len(self.mus), nAsM, vanderBase.shape[1]), dtype = np.complex) radiusb = np.zeros((nbsM, vanderBase.shape[1]), dtype = np.complex) domcoeff = polydomcoeff(self.trainedModel.data.Q.deg[0], self.trainedModel.data.Q.polybasis) Qvals = self.trainedModel.getQVal(self.mus) for k in range(max(nAsM, nbsM)): if k < nAsM: radiusA[:, k :, :] += np.multiply.outer(Qvals * self._fitinv, vanderBase[: nAsM - k, :]) if k < nbsM: radiusb[k :, :] += (self._fitinv.dot(Qvals) * vanderBase[: nbsM - k, :]) Qvals = Qvals * muRTrain if self.POD: radiusA = np.tensordot(self.samplingEngine.RPOD, radiusA, 1) # 'ijkl,klt,ijt->t', resAA, radiusA, radiusA.conj() LL = np.sum(np.tensordot(self.trainedModel.data.resAA, radiusA, 2) * radiusA.conj(), axis = (0, 1)) # 'ijk,jkl,il->l', resAb, radiusA, radiusb.conj() Lf = np.sum(np.tensordot(self.trainedModel.data.resAb[1 :, :, :], radiusA, 2) * radiusb.conj(), axis = 0) # 'ij,jk,ik->k', resbb, radiusb, radiusb.conj() ff = np.sum(self.trainedModel.data.resbb[1 :, 1 :].dot(radiusb) * radiusb.conj(), axis = 0) return domcoeff * np.abs(ff - 2. * np.real(Lf) + LL) ** .5 def errorEstimator(self, mus:Np1D) -> Np1D: """Standard residual-based error estimator.""" self.setupApprox() nAsM = self.HFEngine.nAs - 1 nbsM = max(self.HFEngine.nbs - 1, nAsM * self.homogeneized) muRTest = self.centerNormalize(mus)(0) muRTrain = self.centerNormalize(self.mus)(0) samplingRatio = self._errorSamplingRatio(mus, muRTest, muRTrain) if self.errorEstimatorKind == "EXACT": vanSize = max(nAsM, nbsM) else: vanSize = nbsM vanderBase = np.polynomial.polynomial.polyvander(muRTest, vanSize).T RHSnorms = self._RHSNorms(vanderBase[: nbsM + 1, :]) if self.errorEstimatorKind == "BARE": jOpt = self._errorEstimatorBare() elif self.errorEstimatorKind == "BASIC": idx_muTestSample = np.argmax(samplingRatio) jOpt = self._errorEstimatorBasic(mus[idx_muTestSample], samplingRatio[idx_muTestSample]) else: #if self.errorEstimatorKind == "EXACT": jOpt = self._errorEstimatorExact(muRTrain, vanderBase[: -1, :]) return jOpt * samplingRatio / RHSnorms def setupApprox(self, plotEst : bool = False): """ Compute rational interpolant. SVD-based robust eigenvalue management. """ if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.".format(self.name()), 5) self.computeScaleFactor() if not hasattr(self, "As") or not hasattr(self, "bs"): vbMng(self, "INIT", "Computing affine blocks of system.", 10) self.As = self.HFEngine.affineLinearSystemA(self.mu0, self.scaleFactor)[1 :] self.bs = self.HFEngine.affineLinearSystemb(self.mu0, self.scaleFactor, self.homogeneized) vbMng(self, "DEL", "Done computing affine blocks.", 10) self.greedy(plotEst) self._S = len(self.mus) self._N, self._M = [self._S - 1] * 2 if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelData(self.trainedModel.name(), self.mu0, self.samplingEngine.samples, self.scaleFactor, self.HFEngine.rescalingExp) data.mus = copy(self.mus) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy(self.samplingEngine.samples) self.trainedModel.data.mus = copy(self.mus) self.catchInstability = True if self.N > 0: Qf = self._setupDenominator() Q = Qf[0] if self.errorEstimatorKind == "EXACT": self._fitinv = Qf[1] else: Q = PI() Q.coeffs = np.ones(1, dtype = np.complex) Q.npar = 1 Q.polybasis = self.polybasis if self.errorEstimatorKind == "EXACT": self._fitinv = np.ones(1) self.trainedModel.data.Q = copy(Q) self.trainedModel.data.P = copy(self._setupNumerator()) self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) diff --git a/rrompy/reduction_methods/distributed_greedy/reduced_basis_greedy.py b/rrompy/reduction_methods/greedy/reduced_basis_greedy.py similarity index 97% rename from rrompy/reduction_methods/distributed_greedy/reduced_basis_greedy.py rename to rrompy/reduction_methods/greedy/reduced_basis_greedy.py index 8e85392..55ae357 100644 --- a/rrompy/reduction_methods/distributed_greedy/reduced_basis_greedy.py +++ b/rrompy/reduction_methods/greedy/reduced_basis_greedy.py @@ -1,228 +1,227 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from copy import deepcopy as copy -from .generic_distributed_greedy_approximant import \ - GenericDistributedGreedyApproximant -from rrompy.reduction_methods.distributed import ReducedBasis +from .generic_greedy_approximant import GenericGreedyApproximant +from rrompy.reduction_methods.standard import ReducedBasis from rrompy.reduction_methods.trained_model import \ TrainedModelReducedBasis as tModel from rrompy.reduction_methods.trained_model import TrainedModelData from rrompy.utilities.base.types import Np1D, DictAny, HFEng, paramVal from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import RROMPyWarning, RROMPyAssert from rrompy.parameter import checkParameterList __all__ = ['ReducedBasisGreedy'] -class ReducedBasisGreedy(GenericDistributedGreedyApproximant, ReducedBasis): +class ReducedBasisGreedy(GenericGreedyApproximant, ReducedBasis): """ ROM greedy RB approximant computation for parametric problems. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': number of starting training points; - 'sampler': sample point generator; - 'greedyTol': uniform error tolerance for greedy algorithm; defaults to 1e-2; - 'interactive': whether to interactively terminate greedy algorithm; defaults to False; - 'maxIter': maximum number of greedy steps; defaults to 1e2; - 'refinementRatio': ratio of test points to be exhausted before test set refinement; defaults to 0.2; - 'nTestPoints': number of test points; defaults to 5e2; - 'trainSetGenerator': training sample points generator; defaults to sampler. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots. - 'greedyTol': uniform error tolerance for greedy algorithm; - 'interactive': whether to interactively terminate greedy algorithm; - 'maxIter': maximum number of greedy steps; - 'refinementRatio': ratio of test points to be exhausted before test set refinement; - 'nTestPoints': number of test points; - 'trainSetGenerator': training sample points generator. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. POD: whether to compute POD of snapshots. S: number of test points. sampler: Sample point generator. greedyTol: uniform error tolerance for greedy algorithm. interactive: whether to interactively terminate greedy algorithm. maxIter: maximum number of greedy steps. refinementRatio: ratio of training points to be exhausted before training set refinement. nTestPoints: number of starting training points. trainSetGenerator: training sample points generator. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. estimatorNormEngine: Engine for estimator norm computation. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. As: List of sparse matrices (in CSC format) representing coefficients of linear system matrix. bs: List of numpy vectors representing coefficients of linear system RHS. ARBs: List of sparse matrices (in CSC format) representing coefficients of compressed linear system matrix. bRBs: List of numpy vectors representing coefficients of compressed linear system RHS. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList([], [], toBeExcluded = ["R", "PODTolerance"]) super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self._postInit() @property def R(self): """Value of R.""" self._R = np.prod(self._S) return self._R @R.setter def R(self, R): RROMPyWarning(("R is used just to simplify inheritance, and its value " "cannot be changed from that of prod(S).")) @property def PODTolerance(self): """Value of PODTolerance.""" self._PODTolerance = -1 return self._PODTolerance @PODTolerance.setter def PODTolerance(self, PODTolerance): RROMPyWarning(("PODTolerance is used just to simplify inheritance, " "and its value cannot be changed from -1.")) def errorEstimator(self, mus:Np1D) -> Np1D: """ Standard residual-based error estimator. Unreliable for unstable problems (inf-sup constant is missing). """ self.setupApprox() self.assembleReducedResidualBlocks(full = True) nmus = len(mus) nAs = self.trainedModel.data.resAA.shape[1] nbs = self.trainedModel.data.resbb.shape[0] radiusA = np.empty((len(self.mus), nAs, nmus), dtype = np.complex) radiusb = np.empty((nbs, nmus), dtype = np.complex) mustr = mus if nmus > 2: mustr = "[{} ..({}).. {}]".format(mus[0], nmus - 2, mus[-1]) vbMng(self.trainedModel, "INIT", "Computing RB solution at mu = {}.".format(mustr), 5) verb = self.trainedModel.verbosity self.trainedModel.verbosity = 0 parmus = checkParameterList(mus, self.npar)[0] uApproxRs = self.getApproxReduced(parmus) mu0Eff = self.mu0(0, 0) ** self.HFEngine.rescalingExp[0] for j, muPL in enumerate(parmus): uApproxR = uApproxRs[j] for i in range(max(nAs, nbs)): thetai = ((muPL[0] ** self.HFEngine.rescalingExp[0] - mu0Eff) / self.scaleFactor[0]) ** i if i < nAs: radiusA[:, i, j] = thetai * uApproxR if i < nbs: radiusb[i, j] = thetai self.trainedModel.verbosity = verb vbMng(self.trainedModel, "DEL", "Done computing RB solution.", 5) # 'ij,jk,ik->k', resbb, radiusb, radiusb.conj() ff = np.sum(self.trainedModel.data.resbb.dot(radiusb) * radiusb.conj(), axis = 0) # 'ijk,jkl,il->l', resAb, radiusA, radiusb.conj() Lf = np.sum(np.tensordot(self.trainedModel.data.resAb, radiusA, 2) * radiusb.conj(), axis = 0) # 'ijkl,klt,ijt->t', resAA, radiusA, radiusA.conj() LL = np.sum(np.tensordot(self.trainedModel.data.resAA, radiusA, 2) * radiusA.conj(), axis = (0, 1)) return np.abs((LL - 2. * np.real(Lf) + ff) / ff) ** .5 def setupApprox(self, plotEst : bool = False): """Compute RB projection matrix.""" if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.". format(self.name()), 5) self.computeScaleFactor() self.greedy(plotEst) vbMng(self, "INIT", "Computing projection matrix.", 7) pMat = self.samplingEngine.samples vbMng(self, "INIT", "Computing affine blocks of system.", 10) self.As = self.HFEngine.affineLinearSystemA(self.mu0, self.scaleFactor) self.bs = self.HFEngine.affineLinearSystemb(self.mu0, self.scaleFactor, self.homogeneized) vbMng(self, "DEL", "Done computing affine blocks.", 10) if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelData(self.trainedModel.name(), self.mu0, pMat, self.scaleFactor, self.HFEngine.rescalingExp) ARBs, bRBs = self.assembleReducedSystem(pMat) self.trainedModel.data = data else: self.trainedModel = self.trainedModel pMatOld = self.trainedModel.data.projMat Sold = pMatOld.shape[1] idxNew = list(range(Sold, pMat.shape[1])) ARBs, bRBs = self.assembleReducedSystem(pMat(idxNew), pMatOld) self.trainedModel.data.projMat = copy(pMat) self.trainedModel.data.mus = copy(self.mus) self.trainedModel.data.ARBs = ARBs self.trainedModel.data.bRBs = bRBs vbMng(self, "DEL", "Done computing projection matrix.", 7) self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) diff --git a/rrompy/reduction_methods/pivoting/__init__.py b/rrompy/reduction_methods/pivoted/__init__.py similarity index 100% rename from rrompy/reduction_methods/pivoting/__init__.py rename to rrompy/reduction_methods/pivoted/__init__.py diff --git a/rrompy/reduction_methods/pivoting/generic_pivoted_approximant.py b/rrompy/reduction_methods/pivoted/generic_pivoted_approximant.py similarity index 100% rename from rrompy/reduction_methods/pivoting/generic_pivoted_approximant.py rename to rrompy/reduction_methods/pivoted/generic_pivoted_approximant.py diff --git a/rrompy/reduction_methods/pivoting/rational_interpolant_pivoted.py b/rrompy/reduction_methods/pivoted/rational_interpolant_pivoted.py similarity index 99% rename from rrompy/reduction_methods/pivoting/rational_interpolant_pivoted.py rename to rrompy/reduction_methods/pivoted/rational_interpolant_pivoted.py index d8d277d..33ec944 100644 --- a/rrompy/reduction_methods/pivoting/rational_interpolant_pivoted.py +++ b/rrompy/reduction_methods/pivoted/rational_interpolant_pivoted.py @@ -1,614 +1,614 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np from rrompy.reduction_methods.base import checkRobustTolerance from .generic_pivoted_approximant import GenericPivotedApproximant -from rrompy.reduction_methods.distributed.rational_interpolant import ( +from rrompy.reduction_methods.standard.rational_interpolant import ( RationalInterpolant as RI) from rrompy.utilities.poly_fitting.polynomial import (polybases, polyfitname, nextDerivativeIndices, hashDerivativeToIdx as hashD, hashIdxToDerivative as hashI, homogeneizedpolyvander as hpvP, homogeneizedToFull, PolynomialInterpolator as PI) from rrompy.utilities.poly_fitting.radial_basis import (rbbases, RadialBasisInterpolator as RBI) from rrompy.reduction_methods.trained_model import (TrainedModelPivotedData, TrainedModelPivotedRational as tModel) from rrompy.utilities.base.types import (Np1D, Np2D, HFEng, DictAny, Tuple, List, ListAny, paramVal, paramList) from rrompy.utilities.base import verbosityManager as vbMng, freepar as fp from rrompy.utilities.numerical import multifactorial, customPInv from rrompy.utilities.exception_manager import (RROMPyException, RROMPyAssert, RROMPyWarning) from rrompy.parameter import checkParameter __all__ = ['RationalInterpolantPivoted'] class RationalInterpolantPivoted(GenericPivotedApproximant): """ ROM pivoted rational interpolant computation for parametric problems. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. directionPivot(optional): Pivot components. Defaults to [0]. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator; - 'polybasisPivot': type of polynomial basis for pivot interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'E': number of derivatives used to compute interpolant; defaults to 0; - 'M': degree of rational interpolant numerator; defaults to 0; - 'N': degree of rational interpolant denominator; defaults to 0; - 'MMarginal': degree of marginal interpolant; defaults to 0; - 'radialBasisPivot': radial basis family for pivot numerator; defaults to 0, i.e. no radial basis; - 'radialBasisMarginal': radial basis family for marginal interpolant; defaults to 0, i.e. no radial basis; - 'radialBasisWeightsPivot': radial basis weights for pivot numerator; defaults to 0, i.e. identity; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; defaults to 0, i.e. identity; - 'interpRcondPivot': tolerance for pivot interpolation; defaults to None; - 'interpRcondMarginal': tolerance for marginal interpolation; defaults to None; - 'robustTol': tolerance for robust rational denominator management; defaults to 0. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. directionPivot: Pivot components. mus: Array of snapshot parameters. musPivot: Array of pivot snapshot parameters. musMarginal: Array of marginal snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots; - 'polybasisPivot': type of polynomial basis for pivot interpolation; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; - 'E': number of derivatives used to compute interpolant; - 'M': degree of rational interpolant numerator; - 'N': degree of rational interpolant denominator; - 'MMarginal': degree of marginal interpolant; - 'radialBasisPivot': radial basis family for pivot numerator; - 'radialBasisMarginal': radial basis family for marginal interpolant; - 'radialBasisWeightsPivot': radial basis weights for pivot numerator; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; - 'interpRcondPivot': tolerance for pivot interpolation; - 'interpRcondMarginal': tolerance for marginal interpolation; - 'robustTol': tolerance for robust rational denominator management. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator. POD: Whether to compute POD of snapshots. S: Total number of pivot samples current approximant relies upon. sampler: Pivot sample point generator. polybasisPivot: Type of polynomial basis for pivot interpolation. polybasisMarginal: Type of polynomial basis for marginal interpolation. M: Numerator degree of approximant. N: Denominator degree of approximant. MMarginal: Degree of marginal interpolant. radialBasisPivot: Radial basis family for pivot numerator. radialBasisMarginal: Radial basis family for marginal interpolant. radialBasisWeightsPivot: Radial basis weights for pivot numerator. radialBasisWeightsMarginal: Radial basis weights for marginal interpolant. interpRcondPivot: Tolerance for pivot interpolation. interpRcondMarginal: Tolerance for marginal interpolation. robustTol: Tolerance for robust rational denominator management. E: Complete derivative depth level of S. muBoundsPivot: list of bounds for pivot parameter values. muBoundsMarginal: list of bounds for marginal parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. Q: Numpy 1D vector containing complex coefficients of approximant denominator. P: Numpy 2D vector whose columns are FE dofs of coefficients of approximant numerator. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, directionPivot : ListAny = [0], approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList( ["polybasisPivot", "E", "M", "N", "radialBasisPivot", "radialBasisWeightsPivot", "interpRcondPivot", "robustTol"], ["MONOMIAL", -1, 0, 0, 0, 1, -1, 0]) super().__init__(HFEngine = HFEngine, mu0 = mu0, directionPivot = directionPivot, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self._postInit() @property def polybasisPivot(self): """Value of polybasisPivot.""" return self._polybasisPivot @polybasisPivot.setter def polybasisPivot(self, polybasisPivot): try: polybasisPivot = polybasisPivot.upper().strip().replace(" ","") if polybasisPivot not in polybases: raise RROMPyException( "Prescribed pivot polybasis not recognized.") self._polybasisPivot = polybasisPivot except: RROMPyWarning(("Prescribed pivot polybasis not recognized. " "Overriding to 'MONOMIAL'.")) self._polybasisPivot = "MONOMIAL" self._approxParameters["polybasisPivot"] = self.polybasisPivot @property def radialBasisPivot(self): """Value of radialBasisPivot.""" return self._radialBasisPivot @radialBasisPivot.setter def radialBasisPivot(self, radialBasisPivot): try: if radialBasisPivot != 0: radialBasisPivot = radialBasisPivot.upper().strip().replace( " ","") if radialBasisPivot not in rbbases: raise RROMPyException(("Prescribed pivot radialBasis not " "recognized.")) self._radialBasisPivot = radialBasisPivot except: RROMPyWarning(("Prescribed pivot radialBasis not recognized. " "Overriding to 0.")) self._radialBasisPivot = 0 self._approxParameters["radialBasisPivot"] = self.radialBasisPivot @property def radialBasisWeightsPivot(self): """Value of radialBasisWeightsPivot.""" return self._radialBasisWeightsPivot @radialBasisWeightsPivot.setter def radialBasisWeightsPivot(self, radialBasisWeightsPivot): self._radialBasisWeightsPivot = radialBasisWeightsPivot self._approxParameters["radialBasisWeightsPivot"] = ( self.radialBasisWeightsPivot) @property def polybasisPivotP(self): if self.radialBasisPivot == 0: return self._polybasisPivot return self._polybasisPivot + "_" + self.radialBasisPivot @property def interpRcondPivot(self): """Value of interpRcondPivot.""" return self._interpRcondPivot @interpRcondPivot.setter def interpRcondPivot(self, interpRcondPivot): self._interpRcondPivot = interpRcondPivot self._approxParameters["interpRcondPivot"] = self.interpRcondPivot @property def M(self): """Value of M. Its assignment may change S.""" return self._M @M.setter def M(self, M): if M < 0: raise RROMPyException("M must be non-negative.") self._M = M self._approxParameters["M"] = self.M if hasattr(self, "_E") and self.E >= 0 and self.E < self.M: RROMPyWarning("Prescribed S is too small. Decreasing M.") self.M = self.E @property def N(self): """Value of N. Its assignment may change S.""" return self._N @N.setter def N(self, N): if N < 0: raise RROMPyException("N must be non-negative.") self._N = N self._approxParameters["N"] = self.N if hasattr(self, "_E") and self.E >= 0 and self.E < self.N: RROMPyWarning("Prescribed S is too small. Decreasing N.") self.N = self.E @property def E(self): """Value of E.""" return self._E @E.setter def E(self, E): if E < 0: if not hasattr(self, "_S"): raise RROMPyException(("Value of E must be positive if S is " "not yet assigned.")) E = np.sum(hashI(np.prod(self.S), len(self.directionPivot))) - 1 self._E = E self._approxParameters["E"] = self.E if (hasattr(self, "_S") and self.E >= np.sum(hashI(np.prod(self.S),len(self.directionPivot)))): RROMPyWarning("Prescribed S is too small. Decreasing E.") self.E = -1 if hasattr(self, "_M"): self.M = self.M if hasattr(self, "_N"): self.N = self.N @property def robustTol(self): """Value of tolerance for robust rational denominator management.""" return self._robustTol @robustTol.setter def robustTol(self, robustTol): if robustTol < 0.: RROMPyWarning(("Overriding prescribed negative robustness " "tolerance to 0.")) robustTol = 0. self._robustTol = robustTol self._approxParameters["robustTol"] = self.robustTol @property def S(self): """Value of S.""" return self._S @S.setter def S(self, S): GenericPivotedApproximant.S.fset(self, S) if hasattr(self, "_M"): self.M = self.M if hasattr(self, "_N"): self.N = self.N if hasattr(self, "_E"): self.E = self.E def resetSamples(self): """Reset samples.""" super().resetSamples() self._musPUniqueCN = None self._derPIdxs = None self._reorderP = None def _setupPivotInterpolationIndices(self): """Setup parameters for polyvander.""" RROMPyAssert(self._mode, message = "Cannot setup interpolation indices.") if (self._musPUniqueCN is None or len(self._reorderP) != len(self.musPivot)): self._musPUniqueCN, musPIdxsTo, musPIdxs, musPCount = ( self.centerNormalizePivot(self.musPivot).unique( return_index = True, return_inverse = True, return_counts = True)) self._musPUnique = self.mus[musPIdxsTo] self._derPIdxs = [None] * len(self._musPUniqueCN) self._reorderP = np.empty(len(musPIdxs), dtype = int) filled = 0 for j, cnt in enumerate(musPCount): self._derPIdxs[j] = nextDerivativeIndices([], self.musPivot.shape[1], cnt) jIdx = np.nonzero(musPIdxs == j)[0] self._reorderP[jIdx] = np.arange(filled, filled + cnt) filled += cnt def _setupDenominator(self): """Compute rational denominator.""" RROMPyAssert(self._mode, message = "Cannot setup denominator.") vbMng(self, "INIT", "Starting computation of denominator.", 7) NinvD = None N0 = copy(self.N) qs = [] self.verbosity -= 10 for j in range(len(self.musMarginal)): self._N = N0 while self.N > 0: if NinvD != self.N: invD, fitinvP = self._computeInterpolantInverseBlocks() NinvD = self.N if self.POD: ev, eV = RI.findeveVGQR(self, self.samplingEngine.RPOD[j], invD) else: ev, eV = RI.findeveVGExplicit(self, self.samplingEngine.samples[j], invD) nevBad = checkRobustTolerance(ev, self.robustTol) if nevBad <= 1: break if self.catchInstability: raise RROMPyException(("Instability in denominator " "computation: eigenproblem is " "poorly conditioned.")) RROMPyWarning(("Smallest {} eigenvalues below tolerance. " "Reducing N by 1.").format(nevBad)) self.N = self.N - 1 if self.N <= 0: self._N = 0 eV = np.ones((1, 1)) q = PI() q.npar = self.musPivot.shape[1] q.polybasis = self.polybasisPivot q.coeffs = homogeneizedToFull(tuple([self.N + 1] * q.npar), q.npar, eV[:, 0]) qs = qs + [copy(q)] self.verbosity += 10 vbMng(self, "DEL", "Done computing denominator.", 7) return qs, fitinvP def _setupNumerator(self): """Compute rational numerator.""" RROMPyAssert(self._mode, message = "Cannot setup numerator.") vbMng(self, "INIT", "Starting computation of numerator.", 7) Qevaldiag = np.zeros((len(self.musPivot), len(self.musPivot)), dtype = np.complex) verb = self.trainedModel.verbosity self.trainedModel.verbosity = 0 self._setupPivotInterpolationIndices() M0 = copy(self.M) tensor_idx = 0 ps = [] for k, muM in enumerate(self.musMarginal): self._M = M0 idxGlob = 0 for j, derIdxs in enumerate(self._derPIdxs): mujEff = [fp] * self.npar for jj, kk in enumerate(self.directionPivot): mujEff[kk] = self._musPUnique[j, jj] for jj, kk in enumerate(self.directionMarginal): mujEff[kk] = muM(0, jj) mujEff = checkParameter(mujEff, self.npar) nder = len(derIdxs) idxLoc = np.arange(len(self.musPivot))[ (self._reorderP >= idxGlob) * (self._reorderP < idxGlob + nder)] idxGlob += nder Qval = [0] * nder for der in range(nder): derIdx = hashI(der, self.musPivot.shape[1]) derIdxEff = [0] * self.npar sclEff = [0] * self.npar for jj, kk in enumerate(self.directionPivot): derIdxEff[kk] = derIdx[jj] sclEff[kk] = self.scaleFactorPivot[jj] ** -1. Qval[der] = (self.trainedModel.getQVal(mujEff, derIdxEff, scl = sclEff) / multifactorial(derIdx)) for derU, derUIdx in enumerate(derIdxs): for derQ, derQIdx in enumerate(derIdxs): diffIdx = [x - y for (x, y) in zip(derUIdx, derQIdx)] if all([x >= 0 for x in diffIdx]): diffj = hashD(diffIdx) Qevaldiag[idxLoc[derU], idxLoc[derQ]] = Qval[diffj] while self.M >= 0: if self.radialBasisPivot == 0: p = PI() wellCond, msg = p.setupByInterpolation( self._musPUniqueCN, Qevaldiag, self.M, self.polybasisPivotP, self.verbosity >= 5, True, {"derIdxs": self._derPIdxs, "reorder": self._reorderP, "scl": np.power(self.scaleFactorPivot, -1.)}, {"rcond": self.interpRcondPivot}) else: p = RBI() wellCond, msg = p.setupByInterpolation( self._musPUniqueCN, Qevaldiag, self.M, self.polybasisPivotP, self.radialBasisWeightsPivot, self.verbosity >= 5, True, {"derIdxs": self._derPIdxs, "reorder": self._reorderP, "scl": np.power(self.scaleFactorPivot, -1.)}, {"rcond": self.interpRcondPivot}) vbMng(self, "MAIN", msg, 5) if wellCond: break if self.catchInstability: raise RROMPyException(("Instability in numerator " "computation: polyfit is " "poorly conditioned.")) RROMPyWarning(("Polyfit is poorly conditioned. " "Reducing M by 1.")) self.M -= 1 if self.M < 0: raise RROMPyException(("Instability in computation of " "numerator. Aborting.")) tensor_idx_new = tensor_idx + Qevaldiag.shape[1] if self.POD: p.postmultiplyTensorize(self.samplingEngine.RPODCoalesced.T[ tensor_idx : tensor_idx_new, :]) else: p.pad(tensor_idx, len(self.mus) - tensor_idx_new) tensor_idx = tensor_idx_new ps = ps + [copy(p)] self.trainedModel.verbosity = verb vbMng(self, "DEL", "Done computing numerator.", 7) return ps def setupApprox(self): """ Compute rational interpolant. SVD-based robust eigenvalue management. """ if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.". format(self.name()), 5) self.computeScaleFactor() self.computeSnapshots() if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelPivotedData(self.trainedModel.name(), self.mu0, self.samplingEngine.samplesCoalesced, self.scaleFactor, self.HFEngine.rescalingExp, self.directionPivot) data.musPivot = copy(self.musPivot) data.musMarginal = copy(self.musMarginal) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy(self.samplingEngine.samples) self.trainedModel.data.marginalInterp = self._setupMarginalInterp() if self.N > 0: Qs = self._setupDenominator()[0] else: Q = PI() Q.npar = self.musPivot.shape[1] Q.coeffs = np.ones(tuple([1] * Q.npar), dtype = np.complex) Q.polybasis = self.polybasisPivot Qs = [Q for _ in range(len(self.musMarginal))] self.trainedModel.data.Qs = Qs self.trainedModel.data.Ps = self._setupNumerator() self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) def _computeInterpolantInverseBlocks(self) -> Tuple[List[Np2D], Np2D]: """ Compute inverse factors for minimal interpolant target functional. """ RROMPyAssert(self._mode, message = "Cannot solve eigenvalue problem.") self._setupPivotInterpolationIndices() while self.E >= 0: eWidth = (hashD([self.E + 1] + [0] * (self.musPivot.shape[1] - 1)) - hashD([self.E] + [0] * (self.musPivot.shape[1] - 1))) TE, _, argIdxs = hpvP(self._musPUniqueCN, self.E, self.polybasisPivot, self._derPIdxs, self._reorderP, scl = np.power(self.scaleFactorPivot, -1.)) fitOut = customPInv(TE[:, argIdxs], rcond = self.interpRcondPivot, full = True) vbMng(self, "MAIN", ("Fitting {} samples with degree {} through {}... " "Conditioning of pseudoinverse system: {:.4e}.").format( TE.shape[0], self.E, polyfitname(self.polybasisPivot), fitOut[1][1][0] / fitOut[1][1][-1]), 5) if fitOut[1][0] == len(argIdxs): fitinvP = fitOut[0][- eWidth : , :] break RROMPyWarning("Polyfit is poorly conditioned. Reducing E by 1.") self.E -= 1 if self.E < 0: raise RROMPyException(("Instability in computation of " "denominator. Aborting.")) TN, _, argIdxs = hpvP(self._musPUniqueCN, self.N, self.polybasisPivot, self._derPIdxs, self._reorderP, scl = np.power(self.scaleFactorPivot, -1.)) TN = TN[:, argIdxs] invD = [None] * (eWidth) for k in range(eWidth): pseudoInv = np.diag(fitinvP[k, :]) idxGlob = 0 for j, derIdxs in enumerate(self._derPIdxs): nder = len(derIdxs) idxGlob += nder if nder > 1: idxLoc = np.arange(len(self.musPivot))[ (self._reorderP >= idxGlob - nder) * (self._reorderP < idxGlob)] invLoc = fitinvP[k, idxLoc] pseudoInv[np.ix_(idxLoc, idxLoc)] = 0. for diffj, diffjIdx in enumerate(derIdxs): for derQ, derQIdx in enumerate(derIdxs): derUIdx = [x - y for (x, y) in zip(diffjIdx, derQIdx)] if all([x >= 0 for x in derUIdx]): derU = hashD(derUIdx) pseudoInv[idxLoc[derU], idxLoc[derQ]] = ( invLoc[diffj]) invD[k] = pseudoInv.dot(TN) return invD, fitinvP def centerNormalize(self, mu : paramList = [], mu0 : paramVal = None) -> paramList: """ Compute normalized parameter to be plugged into approximant. Args: mu: Parameter(s) 1. mu0: Parameter(s) 2. If None, set to self.mu0. Returns: Normalized parameter. """ return self.trainedModel.centerNormalize(mu, mu0) def centerNormalizePivot(self, mu : paramList = [], mu0 : paramVal = None) -> paramList: """ Compute normalized parameter to be plugged into approximant. Args: mu: Parameter(s) 1. mu0: Parameter(s) 2. If None, set to self.mu0. Returns: Normalized parameter. """ return self.trainedModel.centerNormalizePivot(mu, mu0) def getResidues(self, *args, **kwargs) -> Np1D: """ Obtain approximant residues. Returns: Matrix with residues as columns. """ return self.trainedModel.getResidues(*args, **kwargs) diff --git a/rrompy/reduction_methods/pivoting/reduced_basis_pivoted.py b/rrompy/reduction_methods/pivoted/reduced_basis_pivoted.py similarity index 100% rename from rrompy/reduction_methods/pivoting/reduced_basis_pivoted.py rename to rrompy/reduction_methods/pivoted/reduced_basis_pivoted.py diff --git a/rrompy/reduction_methods/pole_matching/generic_pole_matching_approximant.py b/rrompy/reduction_methods/pole_matching/generic_pole_matching_approximant.py index f831d2a..660e7d9 100644 --- a/rrompy/reduction_methods/pole_matching/generic_pole_matching_approximant.py +++ b/rrompy/reduction_methods/pole_matching/generic_pole_matching_approximant.py @@ -1,179 +1,179 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from numpy import inf -from rrompy.reduction_methods.pivoting.generic_pivoted_approximant import ( +from rrompy.reduction_methods.pivoted.generic_pivoted_approximant import ( GenericPivotedApproximant) from rrompy.utilities.base.types import ListAny, DictAny, HFEng, paramVal from rrompy.utilities.exception_manager import RROMPyException, RROMPyWarning __all__ = ['GenericPoleMatchingApproximant'] class GenericPoleMatchingApproximant(GenericPivotedApproximant): """ ROM pole matching approximant computation for parametric problems (ABSTRACT). Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. directionPivot(optional): Pivot components. Defaults to [0]. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'matchingWeight': weight for pole matching optimization; defaults to 1; - 'cutOffTolerance': tolerance for ignoring parasitic poles; defaults to np.inf; - 'cutOffType': rule for tolerance computation for parasitic poles; defaults to 'MAGNITUDE'; - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'MMarginal': degree of marginal interpolant; defaults to 0; - 'radialBasisMarginal': radial basis family for marginal interpolant; defaults to 0, i.e. no radial basis; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; defaults to 0, i.e. identity; - 'interpRcondMarginal': tolerance for marginal interpolation; defaults to None. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. directionPivot: Pivot components. mus: Array of snapshot parameters. musPivot: Array of pivot snapshot parameters. musMarginal: Array of marginal snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots; - 'matchingWeight': weight for pole matching optimization; - 'cutOffTolerance': tolerance for ignoring parasitic poles; - 'cutOffType': rule for tolerance computation for parasitic poles; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; - 'MMarginal': degree of marginal interpolant; - 'radialBasisMarginal': radial basis family for marginal interpolant; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; - 'interpRcondMarginal': tolerance for marginal interpolation. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator. POD: Whether to compute POD of snapshots. matchingWeight: Weight for pole matching optimization. cutOffTolerance: Tolerance for ignoring parasitic poles. cutOffType: Rule for tolerance computation for parasitic poles. S: Total number of pivot samples current approximant relies upon. samplerPivot: Pivot sample point generator. SMarginal: Total number of marginal samples current approximant relies upon. samplerMarginal: Marginal sample point generator. polybasisMarginal: Type of polynomial basis for marginal interpolation. MMarginal: Degree of marginal interpolant. radialBasisMarginal: Radial basis family for marginal interpolant. radialBasisWeightsMarginal: Radial basis weights for marginal interpolant. interpRcondMarginal: Tolerance for marginal interpolation. muBoundsPivot: list of bounds for pivot parameter values. muBoundsMarginal: list of bounds for marginal parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, directionPivot : ListAny = [0], approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() if len(directionPivot) > 1: raise RROMPyException(("Exactly 1 pivot parameter allowed in pole " "matching.")) self._addParametersToList(["matchingWeight", "cutOffTolerance", "cutOffType"], [1, inf, "MAGNITUDE"]) super().__init__(HFEngine = HFEngine, mu0 = mu0, directionPivot = directionPivot, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self._postInit() @property def matchingWeight(self): """Value of matchingWeight.""" return self._matchingWeight @matchingWeight.setter def matchingWeight(self, matchingWeight): self._matchingWeight = matchingWeight self._approxParameters["matchingWeight"] = self.matchingWeight @property def cutOffTolerance(self): """Value of cutOffTolerance.""" return self._cutOffTolerance @cutOffTolerance.setter def cutOffTolerance(self, cutOffTolerance): self._cutOffTolerance = cutOffTolerance self._approxParameters["cutOffTolerance"] = self.cutOffTolerance @property def cutOffType(self): """Value of cutOffType.""" return self._cutOffType @cutOffType.setter def cutOffType(self, cutOffType): try: cutOffType = cutOffType.upper().strip().replace(" ","") if cutOffType not in ["MAGNITUDE", "POTENTIAL"]: raise RROMPyException("Prescribed cutOffType not recognized.") self._cutOffType = cutOffType except: RROMPyWarning(("Prescribed cutOffType not recognized. Overriding " "to 'MAGNITUDE'.")) self._cutOffType = "MAGNITUDE" self._approxParameters["cutOffType"] = self.cutOffType diff --git a/rrompy/reduction_methods/pole_matching/rational_interpolant_pole_matching.py b/rrompy/reduction_methods/pole_matching/rational_interpolant_pole_matching.py index 7f8a4f7..5e33c96 100644 --- a/rrompy/reduction_methods/pole_matching/rational_interpolant_pole_matching.py +++ b/rrompy/reduction_methods/pole_matching/rational_interpolant_pole_matching.py @@ -1,222 +1,222 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np -from rrompy.reduction_methods.pivoting.rational_interpolant_pivoted import \ +from rrompy.reduction_methods.pivoted.rational_interpolant_pivoted import \ RationalInterpolantPivoted from .generic_pole_matching_approximant import GenericPoleMatchingApproximant from rrompy.utilities.poly_fitting.polynomial import ( PolynomialInterpolator as PI) from rrompy.reduction_methods.trained_model import (TrainedModelPivotedData, TrainedModelPoleMatchingRational as tModel) from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import RROMPyAssert __all__ = ['RationalInterpolantPoleMatching'] class RationalInterpolantPoleMatching(GenericPoleMatchingApproximant, RationalInterpolantPivoted): """ ROM pivoted rational interpolant computation for parametric problems with pole matching. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. directionPivot(optional): Pivot components. Defaults to [0]. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'matchingWeight': weight for pole matching optimization; defaults to 1; - 'cutOffTolerance': tolerance for ignoring parasitic poles; defaults to np.inf; - 'cutOffType': rule for tolerance computation for parasitic poles; defaults to 'MAGNITUDE'; - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator; - 'polybasisPivot': type of polynomial basis for pivot interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'E': number of derivatives used to compute interpolant; defaults to 0; - 'M': degree of rational interpolant numerator; defaults to 0; - 'N': degree of rational interpolant denominator; defaults to 0; - 'MMarginal': degree of marginal interpolant; defaults to 0; - 'radialBasisPivot': radial basis family for pivot numerator; defaults to 0, i.e. no radial basis; - 'radialBasisMarginal': radial basis family for marginal interpolant; defaults to 0, i.e. no radial basis; - 'radialBasisWeightsPivot': radial basis weights for pivot numerator; defaults to 0, i.e. identity; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; defaults to 0, i.e. identity; - 'interpRcondPivot': tolerance for pivot interpolation; defaults to None; - 'interpRcondMarginal': tolerance for marginal interpolation; defaults to None; - 'robustTol': tolerance for robust rational denominator management; defaults to 0. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. directionPivot: Pivot components. mus: Array of snapshot parameters. musPivot: Array of pivot snapshot parameters. musMarginal: Array of marginal snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots; - 'matchingWeight': weight for pole matching optimization; - 'cutOffTolerance': tolerance for ignoring parasitic poles; - 'cutOffType': rule for tolerance computation for parasitic poles; - 'polybasisPivot': type of polynomial basis for pivot interpolation; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; - 'E': number of derivatives used to compute interpolant; - 'M': degree of rational interpolant numerator; - 'N': degree of rational interpolant denominator; - 'MMarginal': degree of marginal interpolant; - 'radialBasisPivot': radial basis family for pivot numerator; - 'radialBasisMarginal': radial basis family for marginal interpolant; - 'radialBasisWeightsPivot': radial basis weights for pivot numerator; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; - 'interpRcondPivot': tolerance for pivot interpolation; - 'interpRcondMarginal': tolerance for marginal interpolation; - 'robustTol': tolerance for robust rational denominator management. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator. POD: Whether to compute POD of snapshots. matchingWeight: Weight for pole matching optimization. cutOffTolerance: Tolerance for ignoring parasitic poles. cutOffType: Rule for tolerance computation for parasitic poles. S: Total number of pivot samples current approximant relies upon. sampler: Pivot sample point generator. polybasisPivot: Type of polynomial basis for pivot interpolation. polybasisMarginal: Type of polynomial basis for marginal interpolation. M: Numerator degree of approximant. N: Denominator degree of approximant. MMarginal: Degree of marginal interpolant. radialBasisPivot: Radial basis family for pivot numerator. radialBasisMarginal: Radial basis family for marginal interpolant. radialBasisWeightsPivot: Radial basis weights for pivot numerator. radialBasisWeightsMarginal: Radial basis weights for marginal interpolant. interpRcondPivot: Tolerance for pivot interpolation. interpRcondMarginal: Tolerance for marginal interpolation. robustTol: Tolerance for robust rational denominator management. E: Complete derivative depth level of S. muBoundsPivot: list of bounds for pivot parameter values. muBoundsMarginal: list of bounds for marginal parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. Q: Numpy 1D vector containing complex coefficients of approximant denominator. P: Numpy 2D vector whose columns are FE dofs of coefficients of approximant numerator. """ def setupApprox(self): """ Compute rational interpolant. SVD-based robust eigenvalue management. """ if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.". format(self.name()), 5) self.computeScaleFactor() self.computeSnapshots() if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelPivotedData(self.trainedModel.name(), self.mu0, self.samplingEngine.samplesCoalesced, self.scaleFactor, self.HFEngine.rescalingExp, self.directionPivot) data.musPivot = copy(self.musPivot) data.musMarginal = copy(self.musMarginal) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy( self.samplingEngine.samplesCoalesced) self.trainedModel.data.marginalInterp = self._setupMarginalInterp() if self.N > 0: Qs = self._setupDenominator()[0] else: Q = PI() Q.npar = self.musPivot.shape[1] Q.coeffs = np.ones(tuple([1] * Q.npar), dtype = np.complex) Q.polybasis = self.polybasisPivot Qs = [Q for _ in range(len(self.musMarginal))] self.trainedModel.data._temporary = True self.trainedModel.data.Qs = Qs self.trainedModel.data.Ps = self._setupNumerator() vbMng(self, "INIT", "Matching poles.", 10) self.trainedModel.initializeFromRational(self.HFEngine, self.matchingWeight, self.POD) vbMng(self, "DEL", "Done matching poles.", 10) if not np.isinf(self.cutOffTolerance): vbMng(self, "INIT", "Recompressing by cut-off.", 10) msg = self.trainedModel.recompressByCutOff([-1., 1.], self.cutOffTolerance, self.cutOffType) vbMng(self, "DEL", "Done recompressing." + msg, 10) self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) diff --git a/rrompy/reduction_methods/pole_matching/reduced_basis_pole_matching.py b/rrompy/reduction_methods/pole_matching/reduced_basis_pole_matching.py index d3c7aa4..4cf1d65 100644 --- a/rrompy/reduction_methods/pole_matching/reduced_basis_pole_matching.py +++ b/rrompy/reduction_methods/pole_matching/reduced_basis_pole_matching.py @@ -1,190 +1,190 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from numpy import isinf from copy import deepcopy as copy -from rrompy.reduction_methods.pivoting.reduced_basis_pivoted import \ +from rrompy.reduction_methods.pivoted.reduced_basis_pivoted import \ ReducedBasisPivoted from .generic_pole_matching_approximant import GenericPoleMatchingApproximant from rrompy.reduction_methods.trained_model import (TrainedModelPivotedData, TrainedModelPoleMatchingReducedBasis as tModel) from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import RROMPyAssert __all__ = ['ReducedBasisPoleMatching'] class ReducedBasisPoleMatching(GenericPoleMatchingApproximant, ReducedBasisPivoted): """ ROM pivoted RB approximant computation for parametric problems with pole matching. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. directionPivot(optional): Pivot components. Defaults to [0]. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'matchingWeight': weight for pole matching optimization; defaults to 1; - 'cutOffTolerance': tolerance for ignoring parasitic poles; defaults to np.inf; - 'cutOffType': rule for tolerance computation for parasitic poles; defaults to 'MAGNITUDE'; - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator; - 'R': rank for pivot Galerkin projection; defaults to prod(S); - 'PODTolerance': tolerance for pivot snapshots POD; defaults to -1; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'MMarginal': degree of marginal interpolant; defaults to 0; - 'radialBasisMarginal': radial basis family for marginal interpolant; defaults to 0, i.e. no radial basis; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; defaults to 0, i.e. identity; - 'interpRcondMarginal': tolerance for marginal interpolation; defaults to None. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. directionPivot: Pivot components. mus: Array of snapshot parameters. musPivot: Array of pivot snapshot parameters. musMarginal: Array of marginal snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots; - 'matchingWeight': weight for pole matching optimization; - 'cutOffTolerance': tolerance for ignoring parasitic poles; - 'cutOffType': rule for tolerance computation for parasitic poles; - 'R': rank for Galerkin projection; - 'PODTolerance': tolerance for snapshots POD; - 'polybasisMarginal': type of polynomial basis for marginal interpolation; - 'MMarginal': degree of marginal interpolant; - 'radialBasisMarginal': radial basis family for marginal interpolant; - 'radialBasisWeightsMarginal': radial basis weights for marginal interpolant; - 'interpRcondMarginal': tolerance for marginal interpolation. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of pivot samples current approximant relies upon; - 'samplerPivot': pivot sample point generator; - 'SMarginal': total number of marginal samples current approximant relies upon; - 'samplerMarginal': marginal sample point generator. POD: Whether to compute POD of snapshots. matchingWeight: Weight for pole matching optimization. cutOffTolerance: Tolerance for ignoring parasitic poles. cutOffType: Rule for tolerance computation for parasitic poles. S: Total number of pivot samples current approximant relies upon. samplerPivot: Pivot sample point generator. SMarginal: Total number of marginal samples current approximant relies upon. samplerMarginal: Marginal sample point generator. R: Rank for Galerkin projection. PODTolerance: Tolerance for pivot snapshots POD. polybasisMarginal: Type of polynomial basis for marginal interpolation. MMarginal: Degree of marginal interpolant. radialBasisMarginal: Radial basis family for marginal interpolant. radialBasisWeightsMarginal: Radial basis weights for marginal interpolant. interpRcondMarginal: Tolerance for marginal interpolation. muBoundsPivot: list of bounds for pivot parameter values. muBoundsMarginal: list of bounds for marginal parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. As: List of sparse matrices (in CSC format) representing coefficients of linear system matrix. bs: List of numpy vectors representing coefficients of linear system RHS. ARBs: List of sparse matrices (in CSC format) representing coefficients of compressed linear system matrix. bRBs: List of numpy vectors representing coefficients of compressed linear system RHS. """ def setupApprox(self): """Compute RB projection matrix.""" if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.".format(self.name()), 5) self.computeScaleFactor() self.computeSnapshots() self._setupAffineBlocks() pMat = self._setupProjectionMatrix() ARBsList, bRBsList, pList = self.assembleReducedSystemMarginal(pMat) if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelPivotedData(self.trainedModel.name(), self.mu0, pList, self.scaleFactor, self.HFEngine.rescalingExp, self.directionPivot) data.musPivot = copy(self.musPivot) data.musMarginal = copy(self.musMarginal) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy(pList) self.trainedModel.data.marginalInterp = self._setupMarginalInterp() self.trainedModel.data.ARBsList = ARBsList self.trainedModel.data.bRBsList = bRBsList vbMng(self, "INIT", "Matching poles.", 10) self.trainedModel.initializeFromAffine(self.HFEngine, self.matchingWeight, self.POD) vbMng(self, "DEL", "Done matching poles.", 10) if not isinf(self.cutOffTolerance): vbMng(self, "INIT", "Recompressing by cut-off.", 10) msg = self.trainedModel.recompressByCutOff([- 1., 1.], self.cutOffTolerance, self.cutOffType) vbMng(self, "DEL", "Done recompressing." + msg, 10) self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) diff --git a/rrompy/reduction_methods/distributed/__init__.py b/rrompy/reduction_methods/standard/__init__.py similarity index 88% rename from rrompy/reduction_methods/distributed/__init__.py rename to rrompy/reduction_methods/standard/__init__.py index b136774..0ddf98c 100644 --- a/rrompy/reduction_methods/distributed/__init__.py +++ b/rrompy/reduction_methods/standard/__init__.py @@ -1,29 +1,29 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # -from .generic_distributed_approximant import GenericDistributedApproximant +from .generic_standard_approximant import GenericStandardApproximant from .rational_interpolant import RationalInterpolant from .reduced_basis import ReducedBasis __all__ = [ - 'GenericDistributedApproximant', + 'GenericStandardApproximant', 'RationalInterpolant', 'ReducedBasis' ] diff --git a/rrompy/reduction_methods/distributed/generic_distributed_approximant.py b/rrompy/reduction_methods/standard/generic_standard_approximant.py similarity index 98% rename from rrompy/reduction_methods/distributed/generic_distributed_approximant.py rename to rrompy/reduction_methods/standard/generic_standard_approximant.py index af93013..7ce4a2e 100644 --- a/rrompy/reduction_methods/distributed/generic_distributed_approximant.py +++ b/rrompy/reduction_methods/standard/generic_standard_approximant.py @@ -1,163 +1,163 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from copy import deepcopy as copy from rrompy.reduction_methods.base.generic_approximant import ( GenericApproximant) from rrompy.utilities.base.types import DictAny, HFEng, paramVal, paramList from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import RROMPyException, RROMPyAssert from rrompy.parameter import checkParameterList -__all__ = ['GenericDistributedApproximant'] +__all__ = ['GenericStandardApproximant'] -class GenericDistributedApproximant(GenericApproximant): +class GenericStandardApproximant(GenericApproximant): """ ROM interpolant computation for parametric problems (ABSTRACT). Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. POD: Whether to compute POD of snapshots. S: Number of solution snapshots over which current approximant is based upon. sampler: Sample point generator. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() from rrompy.parameter.parameter_sampling import QuadratureSampler as QS self._addParametersToList([], [], ["sampler"], [QS([[0], [1]], "UNIFORM")]) del QS super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self._postInit() @property def mus(self): """Value of mus. Its assignment may reset snapshots.""" return self._mus @mus.setter def mus(self, mus): mus = checkParameterList(mus, self.npar)[0] musOld = copy(self.mus) if hasattr(self, '_mus') else None if (musOld is None or len(mus) != len(musOld) or not mus == musOld): self.resetSamples() self._mus = mus @property def muBounds(self): """Value of muBounds.""" return self.sampler.lims @property def sampler(self): """Value of sampler.""" return self._sampler @sampler.setter def sampler(self, sampler): if 'generatePoints' not in dir(sampler): raise RROMPyException("Sampler type not recognized.") if hasattr(self, '_sampler') and self._sampler is not None: samplerOld = self.sampler self._sampler = sampler self._approxParameters["sampler"] = self.sampler.__str__() if not 'samplerOld' in locals() or samplerOld != self.sampler: self.resetSamples() def setSamples(self, samplingEngine): """Copy samplingEngine and samples.""" super().setSamples(samplingEngine) self.mus = copy(self.samplingEngine.mus) def computeSnapshots(self): """Compute snapshots of solution map.""" RROMPyAssert(self._mode, message = "Cannot start snapshot computation.") if self.samplingEngine.nsamples != np.prod(self.S): vbMng(self, "INIT", "Starting computation of snapshots.", 5) self.mus = self.sampler.generatePoints(self.S) self.samplingEngine.iterSample(self.mus, homogeneized = self.homogeneized) vbMng(self, "DEL", "Done computing snapshots.", 5) def normApprox(self, mu:paramList, homogeneized : bool = False) -> float: """ Compute norm of approximant at arbitrary parameter. Args: mu: Target parameter. homogeneized(optional): Whether to remove Dirichlet BC. Defaults to False. Returns: Target norm of approximant. """ if not self.POD or self.homogeneized != homogeneized: return super().normApprox(mu, homogeneized) return np.linalg.norm(self.getApproxReduced(mu).data, axis = 0) def computeScaleFactor(self): """Compute parameter rescaling factor.""" RROMPyAssert(self._mode, message = "Cannot compute rescaling factor.") self.scaleFactor = .5 * np.abs( self.muBounds[0] ** self.HFEngine.rescalingExp - self.muBounds[1] ** self.HFEngine.rescalingExp) diff --git a/rrompy/reduction_methods/distributed/rational_interpolant.py b/rrompy/reduction_methods/standard/rational_interpolant.py similarity index 99% rename from rrompy/reduction_methods/distributed/rational_interpolant.py rename to rrompy/reduction_methods/standard/rational_interpolant.py index 928ee58..434f291 100644 --- a/rrompy/reduction_methods/distributed/rational_interpolant.py +++ b/rrompy/reduction_methods/standard/rational_interpolant.py @@ -1,559 +1,559 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np from rrompy.reduction_methods.base import checkRobustTolerance -from .generic_distributed_approximant import GenericDistributedApproximant +from .generic_standard_approximant import GenericStandardApproximant from rrompy.utilities.poly_fitting.polynomial import (polybases, polyfitname, nextDerivativeIndices, hashDerivativeToIdx as hashD, hashIdxToDerivative as hashI, homogeneizedpolyvander as hpvP, homogeneizedToFull, PolynomialInterpolator as PI) from rrompy.utilities.poly_fitting.radial_basis import (rbbases, RadialBasisInterpolator as RBI) from rrompy.reduction_methods.trained_model import ( TrainedModelRational as tModel) from rrompy.reduction_methods.trained_model import TrainedModelData from rrompy.utilities.base.types import (Np1D, Np2D, HFEng, DictAny, Tuple, List, paramVal, paramList, sampList) from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.numerical import multifactorial, customPInv from rrompy.utilities.exception_manager import (RROMPyException, RROMPyAssert, RROMPyWarning) __all__ = ['RationalInterpolant'] -class RationalInterpolant(GenericDistributedApproximant): +class RationalInterpolant(GenericStandardApproximant): """ ROM rational interpolant computation for parametric problems. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator; - 'polybasis': type of polynomial basis for interpolation; allowed values include 'MONOMIAL', 'CHEBYSHEV' and 'LEGENDRE'; defaults to 'MONOMIAL'; - 'E': number of derivatives used to compute interpolant; defaults to 0; - 'M': degree of rational interpolant numerator; defaults to 0; - 'N': degree of rational interpolant denominator; defaults to 0; - 'radialBasis': radial basis family for interpolant numerator; defaults to 0, i.e. no radial basis; - 'radialBasisWeights': radial basis weights for interpolant numerator; defaults to 0, i.e. identity; - 'interpRcond': tolerance for interpolation; defaults to None; - 'robustTol': tolerance for robust rational denominator management; defaults to 0. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots; - 'polybasis': type of polynomial basis for interpolation; - 'E': number of derivatives used to compute interpolant; - 'M': degree of rational interpolant numerator; - 'N': degree of rational interpolant denominator; - 'radialBasis': radial basis family for interpolant numerator; - 'radialBasisWeights': radial basis weights for interpolant numerator; - 'interpRcond': tolerance for interpolation via numpy.polyfit; - 'robustTol': tolerance for robust rational denominator management. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator. POD: Whether to compute POD of snapshots. S: Number of solution snapshots over which current approximant is based upon. sampler: Sample point generator. polybasis: type of polynomial basis for interpolation. M: Numerator degree of approximant. N: Denominator degree of approximant. radialBasis: Radial basis family for interpolant numerator. radialBasisWeights: Radial basis weights for interpolant numerator. interpRcond: Tolerance for interpolation via numpy.polyfit. robustTol: Tolerance for robust rational denominator management. E: Complete derivative depth level of S. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. Q: Numpy 1D vector containing complex coefficients of approximant denominator. P: Numpy 2D vector whose columns are FE dofs of coefficients of approximant numerator. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList(["polybasis", "E", "M", "N", "radialBasis", "radialBasisWeights", "interpRcond", "robustTol"], ["MONOMIAL", -1, 0, 0, 0, 1, -1, 0]) super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) self.catchInstability = False self._postInit() @property def polybasis(self): """Value of polybasis.""" return self._polybasis @polybasis.setter def polybasis(self, polybasis): try: polybasis = polybasis.upper().strip().replace(" ","") if polybasis not in polybases: raise RROMPyException("Prescribed polybasis not recognized.") self._polybasis = polybasis except: RROMPyWarning(("Prescribed polybasis not recognized. Overriding " "to 'MONOMIAL'.")) self._polybasis = "MONOMIAL" self._approxParameters["polybasis"] = self.polybasis @property def radialBasis(self): """Value of radialBasis.""" return self._radialBasis @radialBasis.setter def radialBasis(self, radialBasis): try: if radialBasis != 0: radialBasis = radialBasis.upper().strip().replace(" ","") if radialBasis not in rbbases: raise RROMPyException(("Prescribed radialBasis not " "recognized.")) self._radialBasis = radialBasis except: RROMPyWarning(("Prescribed radialBasis not recognized. Overriding " "to 0.")) self._radialBasis = 0 self._approxParameters["radialBasis"] = self.radialBasis @property def polybasisP(self): if self.radialBasis == 0: return self._polybasis return self._polybasis + "_" + self.radialBasis @property def interpRcond(self): """Value of interpRcond.""" return self._interpRcond @interpRcond.setter def interpRcond(self, interpRcond): self._interpRcond = interpRcond self._approxParameters["interpRcond"] = self.interpRcond @property def radialBasisWeights(self): """Value of radialBasisWeights.""" return self._radialBasisWeights @radialBasisWeights.setter def radialBasisWeights(self, radialBasisWeights): self._radialBasisWeights = radialBasisWeights self._approxParameters["radialBasisWeights"] = self.radialBasisWeights @property def M(self): """Value of M. Its assignment may change S.""" return self._M @M.setter def M(self, M): if M < 0: raise RROMPyException("M must be non-negative.") self._M = M self._approxParameters["M"] = self.M if hasattr(self, "_E") and self.E >= 0 and self.E < self.M: RROMPyWarning("Prescribed S is too small. Decreasing M.") self.M = self.E @property def N(self): """Value of N. Its assignment may change S.""" return self._N @N.setter def N(self, N): if N < 0: raise RROMPyException("N must be non-negative.") self._N = N self._approxParameters["N"] = self.N if hasattr(self, "_E") and self.E >= 0 and self.E < self.N: RROMPyWarning("Prescribed S is too small. Decreasing N.") self.N = self.E @property def E(self): """Value of E.""" return self._E @E.setter def E(self, E): if E < 0: if not hasattr(self, "_S"): raise RROMPyException(("Value of E must be positive if S is " "not yet assigned.")) E = np.sum(hashI(np.prod(self.S), self.npar)) - 1 self._E = E self._approxParameters["E"] = self.E if (hasattr(self, "_S") and self.E >= np.sum(hashI(np.prod(self.S), self.npar))): RROMPyWarning("Prescribed S is too small. Decreasing E.") self.E = -1 if hasattr(self, "_M"): self.M = self.M if hasattr(self, "_N"): self.N = self.N @property def robustTol(self): """Value of tolerance for robust rational denominator management.""" return self._robustTol @robustTol.setter def robustTol(self, robustTol): if robustTol < 0.: RROMPyWarning(("Overriding prescribed negative robustness " "tolerance to 0.")) robustTol = 0. self._robustTol = robustTol self._approxParameters["robustTol"] = self.robustTol @property def S(self): """Value of S.""" return self._S @S.setter def S(self, S): - GenericDistributedApproximant.S.fset(self, S) + GenericStandardApproximant.S.fset(self, S) if hasattr(self, "_M"): self.M = self.M if hasattr(self, "_N"): self.N = self.N if hasattr(self, "_E"): self.E = self.E def resetSamples(self): """Reset samples.""" super().resetSamples() self._musUniqueCN = None self._derIdxs = None self._reorder = None def _setupInterpolationIndices(self): """Setup parameters for polyvander.""" RROMPyAssert(self._mode, message = "Cannot setup interpolation indices.") if self._musUniqueCN is None or len(self._reorder) != len(self.mus): self._musUniqueCN, musIdxsTo, musIdxs, musCount = ( self.centerNormalize(self.mus).unique(return_index = True, return_inverse = True, return_counts = True)) self._musUnique = self.mus[musIdxsTo] self._derIdxs = [None] * len(self._musUniqueCN) self._reorder = np.empty(len(musIdxs), dtype = int) filled = 0 for j, cnt in enumerate(musCount): self._derIdxs[j] = nextDerivativeIndices([], self.mus.shape[1], cnt) jIdx = np.nonzero(musIdxs == j)[0] self._reorder[jIdx] = np.arange(filled, filled + cnt) filled += cnt def _setupDenominator(self): """Compute rational denominator.""" RROMPyAssert(self._mode, message = "Cannot setup denominator.") vbMng(self, "INIT", "Starting computation of denominator.", 7) while self.N > 0: invD, fitinv = self._computeInterpolantInverseBlocks() if self.POD: ev, eV = self.findeveVGQR(self.samplingEngine.RPOD, invD) else: ev, eV = self.findeveVGExplicit(self.samplingEngine.samples, invD) nevBad = checkRobustTolerance(ev, self.robustTol) if nevBad <= 1: break if self.catchInstability: raise RROMPyException(("Instability in denominator " "computation: eigenproblem is poorly " "conditioned.")) RROMPyWarning(("Smallest {} eigenvalues below tolerance. Reducing " "N by 1.").format(nevBad)) self.N = self.N - 1 if self.N <= 0: self._N = 0 eV = np.ones((1, 1)) q = PI() q.npar = self.npar q.polybasis = self.polybasis q.coeffs = homogeneizedToFull(tuple([self.N + 1] * self.npar), self.npar, eV[:, 0]) vbMng(self, "DEL", "Done computing denominator.", 7) return q, fitinv def _setupNumerator(self): """Compute rational numerator.""" RROMPyAssert(self._mode, message = "Cannot setup numerator.") vbMng(self, "INIT", "Starting computation of numerator.", 7) Qevaldiag = np.zeros((len(self.mus), len(self.mus)), dtype = np.complex) verb = self.trainedModel.verbosity self.trainedModel.verbosity = 0 self._setupInterpolationIndices() idxGlob = 0 for j, derIdxs in enumerate(self._derIdxs): nder = len(derIdxs) idxLoc = np.arange(len(self.mus))[(self._reorder >= idxGlob) * (self._reorder < idxGlob + nder)] idxGlob += nder Qval = [0] * nder for der in range(nder): derIdx = hashI(der, self.npar) Qval[der] = (self.trainedModel.getQVal( self._musUnique[j], derIdx, scl = np.power(self.scaleFactor, -1.)) / multifactorial(derIdx)) for derU, derUIdx in enumerate(derIdxs): for derQ, derQIdx in enumerate(derIdxs): diffIdx = [x - y for (x, y) in zip(derUIdx, derQIdx)] if all([x >= 0 for x in diffIdx]): diffj = hashD(diffIdx) Qevaldiag[idxLoc[derU], idxLoc[derQ]] = Qval[diffj] if self.POD: Qevaldiag = Qevaldiag.dot(self.samplingEngine.RPOD.T) self.trainedModel.verbosity = verb while self.M >= 0: if self.radialBasis == 0: p = PI() wellCond, msg = p.setupByInterpolation( self._musUniqueCN, Qevaldiag, self.M, self.polybasisP, self.verbosity >= 5, True, {"derIdxs": self._derIdxs, "reorder": self._reorder, "scl": np.power(self.scaleFactor, -1.)}, {"rcond": self.interpRcond}) else: p = RBI() wellCond, msg = p.setupByInterpolation( self._musUniqueCN, Qevaldiag, self.M, self.polybasisP, self.radialBasisWeights, self.verbosity >= 5, True, {"derIdxs": self._derIdxs, "reorder": self._reorder, "scl": np.power(self.scaleFactor, -1.)}, {"rcond": self.interpRcond}) vbMng(self, "MAIN", msg, 5) if wellCond: break if self.catchInstability: raise RROMPyException(("Instability in numerator computation: " "polyfit is poorly conditioned.")) RROMPyWarning("Polyfit is poorly conditioned. Reducing M by 1.") self.M -= 1 if self.M < 0: raise RROMPyException(("Instability in computation of numerator. " "Aborting.")) vbMng(self, "DEL", "Done computing numerator.", 7) return p def setupApprox(self): """ Compute rational interpolant. SVD-based robust eigenvalue management. """ if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.". format(self.name()), 5) self.computeScaleFactor() self.computeSnapshots() if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelData(self.trainedModel.name(), self.mu0, self.samplingEngine.samples, self.scaleFactor, self.HFEngine.rescalingExp) data.mus = copy(self.mus) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy(self.samplingEngine.samples) if self.N > 0: Q = self._setupDenominator()[0] else: Q = PI() Q.coeffs = np.ones(tuple([1] * self.npar), dtype = np.complex) Q.npar = self.npar Q.polybasis = self.polybasis self.trainedModel.data.Q = Q self.trainedModel.data.P = self._setupNumerator() self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) def _computeInterpolantInverseBlocks(self) -> Tuple[List[Np2D], Np2D]: """ Compute inverse factors for minimal interpolant target functional. """ RROMPyAssert(self._mode, message = "Cannot solve eigenvalue problem.") self._setupInterpolationIndices() while self.E >= 0: eWidth = (hashD([self.E + 1] + [0] * (self.npar - 1)) - hashD([self.E] + [0] * (self.npar - 1))) TE, _, argIdxs = hpvP(self._musUniqueCN, self.E, self.polybasis, self._derIdxs, self._reorder, scl = np.power(self.scaleFactor, -1.)) fitOut = customPInv(TE[:, argIdxs], rcond = self.interpRcond, full = True) vbMng(self, "MAIN", ("Fitting {} samples with degree {} through {}... " "Conditioning of pseudoinverse system: {:.4e}.").format( TE.shape[0], self.E, polyfitname(self.polybasis), fitOut[1][1][0] / fitOut[1][1][-1]), 5) if fitOut[1][0] == len(argIdxs): fitinv = fitOut[0][- eWidth : , :] break RROMPyWarning("Polyfit is poorly conditioned. Reducing E by 1.") self.E -= 1 if self.E < 0: raise RROMPyException(("Instability in computation of " "denominator. Aborting.")) TN, _, argIdxs = hpvP(self._musUniqueCN, self.N, self.polybasis, self._derIdxs, self._reorder, scl = np.power(self.scaleFactor, -1.)) TN = TN[:, argIdxs] invD = [None] * (eWidth) for k in range(eWidth): pseudoInv = np.diag(fitinv[k, :]) idxGlob = 0 for j, derIdxs in enumerate(self._derIdxs): nder = len(derIdxs) idxGlob += nder if nder > 1: idxLoc = np.arange(len(self.mus))[ (self._reorder >= idxGlob - nder) * (self._reorder < idxGlob)] invLoc = fitinv[k, idxLoc] pseudoInv[np.ix_(idxLoc, idxLoc)] = 0. for diffj, diffjIdx in enumerate(derIdxs): for derQ, derQIdx in enumerate(derIdxs): derUIdx = [x - y for (x, y) in zip(diffjIdx, derQIdx)] if all([x >= 0 for x in derUIdx]): derU = hashD(derUIdx) pseudoInv[idxLoc[derU], idxLoc[derQ]] = ( invLoc[diffj]) invD[k] = pseudoInv.dot(TN) return invD, fitinv def findeveVGExplicit(self, sampleE:sampList, invD:List[Np2D]) -> Tuple[Np1D, Np2D]: """ Compute explicitly eigenvalues and eigenvectors of rational denominator matrix. """ RROMPyAssert(self._mode, message = "Cannot solve eigenvalue problem.") nEnd = invD[0].shape[1] eWidth = len(invD) vbMng(self, "INIT", "Building gramian matrix.", 10) gramian = self.HFEngine.innerProduct(sampleE, sampleE) G = np.zeros((nEnd, nEnd), dtype = np.complex) for k in range(eWidth): G += invD[k].T.conj().dot(gramian.dot(invD[k])) vbMng(self, "DEL", "Done building gramian.", 10) vbMng(self, "INIT", "Solving eigenvalue problem for gramian matrix.", 7) ev, eV = np.linalg.eigh(G) vbMng(self, "MAIN", ("Solved eigenvalue problem of size {} with condition number " "{:.4e}.").format(nEnd, ev[-1] / ev[0]), 5) vbMng(self, "DEL", "Done solving eigenvalue problem.", 7) return ev, eV def findeveVGQR(self, RPODE:Np2D, invD:List[Np2D]) -> Tuple[Np1D, Np2D]: """ Compute eigenvalues and eigenvectors of rational denominator matrix through SVD of R factor. """ RROMPyAssert(self._mode, message = "Cannot solve eigenvalue problem.") nEnd = invD[0].shape[1] S = RPODE.shape[0] eWidth = len(invD) vbMng(self, "INIT", "Building half-gramian matrix stack.", 10) Rstack = np.zeros((S * eWidth, nEnd), dtype = np.complex) for k in range(eWidth): Rstack[k * S : (k + 1) * S, :] = RPODE.dot(invD[k]) vbMng(self, "DEL", "Done building half-gramian.", 10) vbMng(self, "INIT", "Solving svd for square root of gramian matrix.", 7) _, s, eV = np.linalg.svd(Rstack, full_matrices = False) ev = s[::-1] eV = eV[::-1, :].T.conj() vbMng(self, "MAIN", ("Solved svd problem of size {} x {} with condition number " "{:.4e}.").format(*Rstack.shape, s[0] / s[-1]), 5) vbMng(self, "DEL", "Done solving svd.", 7) return ev, eV def centerNormalize(self, mu : paramList = [], mu0 : paramVal = None) -> paramList: """ Compute normalized parameter to be plugged into approximant. Args: mu: Parameter(s) 1. mu0: Parameter(s) 2. If None, set to self.mu0. Returns: Normalized parameter. """ return self.trainedModel.centerNormalize(mu, mu0) def getResidues(self, *args, **kwargs) -> Np1D: """ Obtain approximant residues. Returns: Matrix with residues as columns. """ return self.trainedModel.getResidues(*args, **kwargs) diff --git a/rrompy/reduction_methods/distributed/reduced_basis.py b/rrompy/reduction_methods/standard/reduced_basis.py similarity index 98% rename from rrompy/reduction_methods/distributed/reduced_basis.py rename to rrompy/reduction_methods/standard/reduced_basis.py index d63bbf4..ac53d48 100644 --- a/rrompy/reduction_methods/distributed/reduced_basis.py +++ b/rrompy/reduction_methods/standard/reduced_basis.py @@ -1,209 +1,209 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # from copy import deepcopy as copy import numpy as np -from .generic_distributed_approximant import GenericDistributedApproximant +from .generic_standard_approximant import GenericStandardApproximant from rrompy.reduction_methods.trained_model import \ TrainedModelReducedBasis as tModel from rrompy.reduction_methods.trained_model import TrainedModelData from rrompy.reduction_methods.base.reduced_basis_utils import \ projectAffineDecomposition from rrompy.utilities.base.types import (Np1D, Np2D, List, ListAny, Tuple, DictAny, HFEng, paramVal, sampList) from rrompy.utilities.base import verbosityManager as vbMng from rrompy.utilities.exception_manager import (RROMPyWarning, RROMPyException, RROMPyAssert) __all__ = ['ReducedBasis'] -class ReducedBasis(GenericDistributedApproximant): +class ReducedBasis(GenericStandardApproximant): """ ROM RB approximant computation for parametric problems. Args: HFEngine: HF problem solver. mu0(optional): Default parameter. Defaults to 0. approxParameters(optional): Dictionary containing values for main parameters of approximant. Recognized keys are: - 'POD': whether to compute POD of snapshots; defaults to True; - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator; - 'R': rank for Galerkin projection; defaults to prod(S); - 'PODTolerance': tolerance for snapshots POD; defaults to -1. Defaults to empty dict. homogeneized(optional): Whether to homogeneize Dirichlet BCs. Defaults to False. verbosity(optional): Verbosity level. Defaults to 10. Attributes: HFEngine: HF problem solver. mu0: Default parameter. mus: Array of snapshot parameters. homogeneized: Whether to homogeneize Dirichlet BCs. approxRadius: Dummy radius of approximant (i.e. distance from mu0 to farthest sample point). approxParameters: Dictionary containing values for main parameters of approximant. Recognized keys are in parameterList. parameterListSoft: Recognized keys of soft approximant parameters: - 'POD': whether to compute POD of snapshots. - 'R': rank for Galerkin projection; - 'PODTolerance': tolerance for snapshots POD. parameterListCritical: Recognized keys of critical approximant parameters: - 'S': total number of samples current approximant relies upon; - 'sampler': sample point generator; POD: Whether to compute POD of snapshots. S: Number of solution snapshots over which current approximant is based upon. sampler: Sample point generator. R: Rank for Galerkin projection. muBounds: list of bounds for parameter values. samplingEngine: Sampling engine. uHF: High fidelity solution(s) with parameter(s) lastSolvedHF as sampleList. lastSolvedHF: Parameter(s) corresponding to last computed high fidelity solution(s) as parameterList. uApproxReduced: Reduced approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApproxReduced: Parameter(s) corresponding to last computed reduced approximate solution(s) as parameterList. uApprox: Approximate solution(s) with parameter(s) lastSolvedApprox as sampleList. lastSolvedApprox: Parameter(s) corresponding to last computed approximate solution(s) as parameterList. As: List of sparse matrices (in CSC format) representing coefficients of linear system matrix. bs: List of numpy vectors representing coefficients of linear system RHS. ARBs: List of sparse matrices (in CSC format) representing coefficients of compressed linear system matrix. bRBs: List of numpy vectors representing coefficients of compressed linear system RHS. """ def __init__(self, HFEngine:HFEng, mu0 : paramVal = None, approxParameters : DictAny = {}, homogeneized : bool = False, verbosity : int = 10, timestamp : bool = True): self._preInit() self._addParametersToList(["R", "PODTolerance"], [1, -1]) super().__init__(HFEngine = HFEngine, mu0 = mu0, approxParameters = approxParameters, homogeneized = homogeneized, verbosity = verbosity, timestamp = timestamp) vbMng(self, "INIT", "Computing affine blocks of system.", 10) vbMng(self, "DEL", "Done computing affine blocks.", 10) self._postInit() @property def S(self): """Value of S.""" return self._S @S.setter def S(self, S): - GenericDistributedApproximant.S.fset(self, S) + GenericStandardApproximant.S.fset(self, S) if not hasattr(self, "_R"): self._R = np.prod(self.S) @property def R(self): """Value of R. Its assignment may change S.""" return self._R @R.setter def R(self, R): if R < 0: raise RROMPyException("R must be non-negative.") self._R = R self._approxParameters["R"] = self.R if hasattr(self, "_S") and np.prod(self.S) < self.R: RROMPyWarning("Prescribed S is too small. Decreasing R.") self.R = np.prod(self.S) @property def PODTolerance(self): """Value of PODTolerance.""" return self._PODTolerance @PODTolerance.setter def PODTolerance(self, PODTolerance): self._PODTolerance = PODTolerance self._approxParameters["PODTolerance"] = self.PODTolerance def setupApprox(self): """Compute RB projection matrix.""" if self.checkComputedApprox(): return RROMPyAssert(self._mode, message = "Cannot setup approximant.") vbMng(self, "INIT", "Setting up {}.". format(self.name()), 5) self.computeScaleFactor() self.computeSnapshots() vbMng(self, "INIT", "Computing projection matrix.", 7) if self.POD: U, s, _ = np.linalg.svd(self.samplingEngine.RPOD) s = s ** 2. else: Gramian = self.HFEngine.innerProduct(self.samplingEngine.samples, self.samplingEngine.samples) U, s, _ = np.linalg.svd(Gramian) nsamples = self.samplingEngine.nsamples snorm = np.cumsum(s[::-1]) / np.sum(s) nPODTrunc = min(nsamples - np.argmax(snorm > self.PODTolerance), self.R) pMat = self.samplingEngine.samples.dot(U[:, : nPODTrunc]) vbMng(self, "MAIN", ("Assembling {}x{} projection matrix from {} " "samples.").format(*(pMat.shape), nsamples), 5) if self.trainedModel is None: self.trainedModel = tModel() self.trainedModel.verbosity = self.verbosity self.trainedModel.timestamp = self.timestamp data = TrainedModelData(self.trainedModel.name(), self.mu0, pMat, self.scaleFactor, self.HFEngine.rescalingExp) data.mus = copy(self.mus) self.trainedModel.data = data else: self.trainedModel = self.trainedModel self.trainedModel.data.projMat = copy(pMat) vbMng(self, "INIT", "Computing affine blocks of system.", 10) self.As = self.HFEngine.affineLinearSystemA(self.mu0, self.scaleFactor) self.bs = self.HFEngine.affineLinearSystemb(self.mu0, self.scaleFactor, self.homogeneized) vbMng(self, "DEL", "Done computing affine blocks.", 10) ARBs, bRBs = self.assembleReducedSystem(pMat) self.trainedModel.data.ARBs = ARBs self.trainedModel.data.bRBs = bRBs vbMng(self, "DEL", "Done computing projection matrix.", 7) self.trainedModel.data.approxParameters = copy(self.approxParameters) vbMng(self, "DEL", "Done setting up approximant.", 5) def assembleReducedSystem(self, pMat : sampList = None, pMatOld : sampList = None)\ -> Tuple[List[Np2D], List[Np1D]]: """Build affine blocks of RB linear system through projections.""" if pMat is None: self.setupApprox() ARBs = self.trainedModel.data.ARBs bRBs = self.trainedModel.data.bRBs else: vbMng(self, "INIT", "Projecting affine terms of HF model.", 10) ARBsOld = None if pMatOld is None else self.trainedModel.data.ARBs bRBsOld = None if pMatOld is None else self.trainedModel.data.bRBs ARBs, bRBs = projectAffineDecomposition(self.As, self.bs, pMat, ARBsOld, bRBsOld, pMatOld) vbMng(self, "DEL", "Done projecting affine terms.", 10) return ARBs, bRBs diff --git a/tests/reduction_methods_1D/rational_interpolant_1d.py b/tests/reduction_methods_1D/rational_interpolant_1d.py index 5011114..b8bd6ac 100644 --- a/tests/reduction_methods_1D/rational_interpolant_1d.py +++ b/tests/reduction_methods_1D/rational_interpolant_1d.py @@ -1,68 +1,68 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_fft import matrixFFT -from rrompy.reduction_methods.distributed import RationalInterpolant as RI +from rrompy.reduction_methods.standard import RationalInterpolant as RI from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, ManualSampler as MS) from rrompy.parameter import checkParameterList def test_monomials(capsys): mu = 1.5 solver = matrixFFT() params = {"POD": False, "M": 9, "N": 9, "S": 10, "robustTol": 1e-6, "interpRcond": 1e-3, "polybasis": "MONOMIAL", "sampler": QS([1.5, 6.5], "UNIFORM")} approx = RI(solver, 4., params, verbosity = 0) approx.setupApprox() out, err = capsys.readouterr() assert "poorly conditioned. Reducing E " in out assert len(err) == 0 assert np.isclose(approx.normErr(mu)[0], 2.9051e-4, atol = 1e-4) def test_well_cond(): mu = 1.5 solver = matrixFFT() params = {"POD": True, "M": 9, "N": 9, "S": 10, "robustTol": 1e-14, "interpRcond": 1e-10, "polybasis": "CHEBYSHEV", "sampler": QS([1., 7.], "CHEBYSHEV")} approx = RI(solver, 4., params, verbosity = 0) approx.setupApprox() poles = approx.getPoles() for lambda_ in np.arange(1, 8): assert np.isclose(np.min(np.abs(poles - lambda_)), 0., atol = 1e-4) for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-8) def test_hermite(): mu = 1.5 solver = matrixFFT() sampler0 = QS([1., 7.], "CHEBYSHEV") points, _ = checkParameterList(np.tile(sampler0.generatePoints(4)(0), 3)) params = {"POD": True, "M": 11, "N": 11, "S": 12, "polybasis": "CHEBYSHEV", "sampler": MS([1., 7.], points = points)} approx = RI(solver, 4., params, verbosity = 0) approx.setupApprox() poles = approx.getPoles() for lambda_ in np.arange(1, 8): assert np.isclose(np.min(np.abs(poles - lambda_)), 0., atol = 1e-4) for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-8) diff --git a/tests/reduction_methods_1D/rational_interpolant_greedy_1d.py b/tests/reduction_methods_1D/rational_interpolant_greedy_1d.py index 4ceb0ee..d57d9e2 100644 --- a/tests/reduction_methods_1D/rational_interpolant_greedy_1d.py +++ b/tests/reduction_methods_1D/rational_interpolant_greedy_1d.py @@ -1,94 +1,93 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_fft import matrixFFT -from rrompy.reduction_methods.distributed_greedy import \ - RationalInterpolantGreedy as RIG +from rrompy.reduction_methods.greedy import RationalInterpolantGreedy as RIG from rrompy.parameter.parameter_sampling import QuadratureSampler as QS def test_lax_tolerance(capsys): mu = 2.25 solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 4, "polybasis": "CHEBYSHEV", "greedyTol": 1e-2, "errorEstimatorKind": "bare", "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx = RIG(solver, 4., params, verbosity = 100) approx.greedy() out, err = capsys.readouterr() assert "Done computing snapshots (final snapshot count: 10)." in out assert len(err) == 0 assert np.isclose(approx.normErr(mu)[0], 2.169678e-4, rtol = 1e-1) def test_samples_at_poles(): solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 4, "nTestPoints": 100, "polybasis": "CHEBYSHEV", "greedyTol": 1e-5, "errorEstimatorKind": "exact", "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx = RIG(solver, 4., params, verbosity = 0) approx.greedy() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0] / (1e-15+approx.normHF(mu)[0]), 0., atol = 1e-4) poles = approx.getPoles() for lambda_ in range(2, 7): assert np.isclose(np.min(np.abs(poles - lambda_)), 0., atol = 1e-3) assert np.isclose(np.min(np.abs(np.array(approx.mus(0)) - lambda_)), 0., atol = 1e-1) def test_maxIter(): solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 5, "nTestPoints": 500, "polybasis": "CHEBYSHEV", "greedyTol": 1e-6, "maxIter": 10, "errorEstimatorKind": "basic", "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx = RIG(solver, 4., params, verbosity = 0) approx.input = lambda: "N" approx.greedy() assert len(approx.mus) == 10 _, _, maxEst = approx.getMaxErrorEstimator(approx.muTest) assert maxEst > 1e-6 def test_load_copy(capsys): mu = 3. solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 4, "nTestPoints": 100, "polybasis": "CHEBYSHEV", "greedyTol": 1e-5, "errorEstimatorKind": "exact", "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx1 = RIG(solver, 4., params, verbosity = 100) approx1.greedy() err1 = approx1.normErr(mu)[0] out, err = capsys.readouterr() assert "Solving HF model for mu =" in out assert len(err) == 0 approx2 = RIG(solver, 4., params, verbosity = 100) approx2.setTrainedModel(approx1) approx2.setHF(mu, approx1.uHF) err2 = approx2.normErr(mu)[0] out, err = capsys.readouterr() assert "Solving HF model for mu =" not in out assert len(err) == 0 assert np.isclose(err1, err2, rtol = 1e-10) diff --git a/tests/reduction_methods_1D/reduced_basis_distributed_1d.py b/tests/reduction_methods_1D/reduced_basis_1d.py similarity index 96% rename from tests/reduction_methods_1D/reduced_basis_distributed_1d.py rename to tests/reduction_methods_1D/reduced_basis_1d.py index 6905e65..3cd2a78 100644 --- a/tests/reduction_methods_1D/reduced_basis_distributed_1d.py +++ b/tests/reduction_methods_1D/reduced_basis_1d.py @@ -1,57 +1,57 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_fft import matrixFFT -from rrompy.reduction_methods.distributed import ReducedBasis as RB +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, ManualSampler as MS) from rrompy.parameter import checkParameterList def test_LS(): solver = matrixFFT() params = {"POD": True, "R": 5, "S": 10, "sampler": QS([1., 7.], "CHEBYSHEV")} approx = RB(solver, 4., params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert not np.isclose(approx.normErr(mu)[0], 0., atol = 1e-7) approx.POD = False approx.setupApprox() for mu in approx.mus[approx.R :]: assert not np.isclose(approx.normErr(mu)[0], 0., atol = 1e-3) def test_interp(): solver = matrixFFT() params = {"POD": False, "S": 10, "sampler": QS([1., 7.], "CHEBYSHEV")} approx = RB(solver, 4., params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-7) def test_hermite(): mu = 1.5 solver = matrixFFT() sampler0 = QS([1., 7.], "CHEBYSHEV") points, _ = checkParameterList(np.tile(sampler0.generatePoints(4)(0), 3)) params = {"POD": True, "S": 12, "sampler": MS([1., 7.], points = points)} approx = RB(solver, 4., params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-8) diff --git a/tests/reduction_methods_1D/reduced_basis_distributed_greedy_1d.py b/tests/reduction_methods_1D/reduced_basis_greedy_1d.py similarity index 93% rename from tests/reduction_methods_1D/reduced_basis_distributed_greedy_1d.py rename to tests/reduction_methods_1D/reduced_basis_greedy_1d.py index e0a2462..0086ab0 100644 --- a/tests/reduction_methods_1D/reduced_basis_distributed_greedy_1d.py +++ b/tests/reduction_methods_1D/reduced_basis_greedy_1d.py @@ -1,60 +1,59 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_fft import matrixFFT -from rrompy.reduction_methods.distributed_greedy import ReducedBasisGreedy \ - as RBG +from rrompy.reduction_methods.greedy import ReducedBasisGreedy as RBG from rrompy.parameter.parameter_sampling import QuadratureSampler as QS def test_lax_tolerance(capsys): mu = 2.25 solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 4, "greedyTol": 1e-2, "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx = RBG(solver, 4., params, verbosity = 10) approx.greedy() out, err = capsys.readouterr() assert "Done computing snapshots (final snapshot count: 10)." in out assert len(err) == 0 assert len(approx.mus) == 10 _, _, maxEst = approx.getMaxErrorEstimator(approx.muTest) assert maxEst < 1e-2 assert np.isclose(approx.normErr(mu)[0], 1.5056e-05, rtol = 1e-1) def test_samples_at_poles(): solver = matrixFFT() params = {"POD": True, "sampler": QS([1.5, 6.5], "UNIFORM"), "S": 4, "nTestPoints": 100, "greedyTol": 1e-5, "trainSetGenerator": QS([1.5, 6.5], "CHEBYSHEV")} approx = RBG(solver, 4., params, verbosity = 0) approx.greedy() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0] / (1e-15+approx.normHF(mu)[0]), 0., atol = 1e-4) poles = approx.getPoles() for lambda_ in range(2, 7): assert np.isclose(np.min(np.abs(poles - lambda_)), 0., atol = 1e-3) assert np.isclose(np.min(np.abs(np.array(approx.mus(0)) - lambda_)), 0., atol = 1e-1) diff --git a/tests/reduction_methods_multiD/rational_interpolant_2d.py b/tests/reduction_methods_multiD/rational_interpolant_2d.py index fe75aa8..0788552 100644 --- a/tests/reduction_methods_multiD/rational_interpolant_2d.py +++ b/tests/reduction_methods_multiD/rational_interpolant_2d.py @@ -1,79 +1,79 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_random import matrixRandom -from rrompy.reduction_methods.distributed import RationalInterpolant as RI +from rrompy.reduction_methods.standard import RationalInterpolant as RI from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, ManualSampler as MS) def test_monomials(capsys): mu = [5.05, 7.1] mu0 = [5., 7.] solver = matrixRandom() uh = solver.solve(mu)[0] params = {"POD": False, "M": 4, "N": 4, "S": [4, 4], "robustTol": 1e-6, "interpRcond": 1e-3, "polybasis": "MONOMIAL", "sampler": QS([[4.9, 6.85], [5.1, 7.15]], "UNIFORM")} approx = RI(solver, mu0, params, verbosity = 0) approx.setupApprox() uhP1 = approx.getApprox(mu)[0] errP = approx.getErr(mu)[0] errNP = approx.normErr(mu)[0] myerrP = uhP1 - uh assert np.allclose(np.abs(errP - myerrP), 0., rtol = 1e-3) assert np.isclose(solver.norm(errP), errNP, rtol = 1e-3) resP = approx.getRes(mu)[0] resNP = approx.normRes(mu) assert np.isclose(solver.norm(resP), resNP, rtol = 1e-3) assert np.allclose(np.abs(resP - (solver.b(mu) - solver.A(mu).dot(uhP1))), 0., rtol = 1e-3) assert np.isclose(errNP / solver.norm(uh), 5.2667e-05, rtol = 1e-1) out, err = capsys.readouterr() print(out) assert ("poorly conditioned. Reducing E" in out) assert len(err) == 0 def test_well_cond(): mu = [5.05, 7.1] mu0 = [5., 7.] solver = matrixRandom() params = {"POD": True, "M": 3, "N": 3, "S": [4, 4], "interpRcond": 1e-10, "polybasis": "CHEBYSHEV", "sampler": QS([[4.9, 6.85], [5.1, 7.15]], "UNIFORM")} approx = RI(solver, mu0, params, verbosity = 0) approx.setupApprox() print(approx.normErr(mu)[0] / approx.normHF(mu)[0]) assert np.isclose(approx.normErr(mu)[0] / approx.normHF(mu)[0], 5.98695e-05, rtol = 1e-1) def test_hermite(): mu = [5.05, 7.1] mu0 = [5., 7.] solver = matrixRandom() sampler0 = QS([[4.9, 6.85], [5.1, 7.15]], "UNIFORM") params = {"POD": True, "M": 3, "N": 3, "S": [25], "polybasis": "CHEBYSHEV", "sampler": MS([[4.9, 6.85], [5.1, 7.15]], points = sampler0.generatePoints([3, 3]))} approx = RI(solver, mu0, params, verbosity = 0) approx.setupApprox() assert np.isclose(approx.normErr(mu)[0] / approx.normHF(mu)[0], 0.000236598, rtol = 1e-1) diff --git a/tests/reduction_methods_multiD/reduced_basis_distributed_2d.py b/tests/reduction_methods_multiD/reduced_basis_2d.py similarity index 97% rename from tests/reduction_methods_multiD/reduced_basis_distributed_2d.py rename to tests/reduction_methods_multiD/reduced_basis_2d.py index 2008338..5a66aa1 100644 --- a/tests/reduction_methods_multiD/reduced_basis_distributed_2d.py +++ b/tests/reduction_methods_multiD/reduced_basis_2d.py @@ -1,62 +1,62 @@ # Copyright (C) 2018 by the RROMPy authors # # This file is part of RROMPy. # # RROMPy is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # RROMPy is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public License # along with RROMPy. If not, see . # import numpy as np from matrix_random import matrixRandom -from rrompy.reduction_methods.distributed import ReducedBasis as RB +from rrompy.reduction_methods.standard import ReducedBasis as RB from rrompy.parameter.parameter_sampling import (QuadratureSampler as QS, ManualSampler as MS) from rrompy.parameter import checkParameterList def test_LS(): mu0 = [2, 3] solver = matrixRandom() params = {"POD": True, "R": 5, "S": [3, 3], "sampler": QS([[0., 4.], [1., 5.]], "CHEBYSHEV")} approx = RB(solver, mu0, params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert not np.isclose(approx.normErr(mu)[0], 0., atol = 1e-7) approx.POD = False approx.setupApprox() for mu in approx.mus[approx.R :]: assert not np.isclose(approx.normErr(mu)[0], 0., atol = 1e-3) def test_interp(): mu0 = [2, 3] solver = matrixRandom() params = {"POD": False, "S": [3, 3], "sampler": QS([[0., 4.], [1., 5.]], "CHEBYSHEV")} approx = RB(solver, mu0, params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-7) def test_hermite(): mu0 = [2, 3] solver = matrixRandom() sampler0 = QS([[0., 4.], [1., 5.]], "CHEBYSHEV") points, _ = checkParameterList(np.tile( sampler0.generatePoints([2, 2]).data, [3, 1])) params = {"POD": True, "S": [12], "sampler": MS([[0., 4.], [1., 5.]], points = points)} approx = RB(solver, mu0, params, verbosity = 0) approx.setupApprox() for mu in approx.mus: assert np.isclose(approx.normErr(mu)[0], 0., atol = 1e-8)