From e5ffa8f3ea81d6af4cfd85005aa95a73ea403407 Mon Sep 17 00:00:00 2001 From: Bernardo Abreu Figueiredo Date: Tue, 10 Sep 2024 17:27:49 +0200 Subject: [PATCH 1/5] added example for homotopy (almost same as basic one, ne) --- examples/match/000_match_basic_homotopy.py | 77 ++++++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 examples/match/000_match_basic_homotopy.py diff --git a/examples/match/000_match_basic_homotopy.py b/examples/match/000_match_basic_homotopy.py new file mode 100644 index 000000000..35b054d93 --- /dev/null +++ b/examples/match/000_match_basic_homotopy.py @@ -0,0 +1,77 @@ +import xtrack as xt +import matplotlib.pyplot as plt +import numpy as np + +# Load a line and build a tracker +line = xt.Line.from_json('../../test_data/hllhc15_thick/lhc_thick_with_knobs.json') +line.build_tracker() + +# Match tunes and chromaticities to assigned values +opt = line.match( + solve=False, + method='4d', # <- passed to twiss + vary=[ + xt.VaryList(['kqtf.b1', 'kqtd.b1'], step=1e-8, tag='quad'), + xt.VaryList(['ksf.b1', 'ksd.b1'], step=1e-4, limits=[-0.1, 0.1], tag='sext'), + ], + targets = [ + xt.TargetSet(qx=62.315, qy=60.325, tol=1e-6, tag='tune'), + xt.TargetSet(dqx=10.0, dqy=12.0, tol=0.01, tag='chrom'), + ]) + +opt.solve_homotopy() + +# Inspect optimization log +opt.log() + +# prints: +# iteration penalty alpha tag tol_met target_active hit_limits vary_active vary_0 ... +# 0 12.8203 -1 nnnn yyyy nnnn yyyy 0 +# 1 0.00207829 0 yyyy yyyy nnnn yyyy 4.27447e-06 +# 2 0.00207829 -1 Homotopy it 0 yyyy yyyy nnnn yyyy 4.27447e-06 +# 3 0.0033512 0 yyyy yyyy nnnn yyyy 8.54459e-06 +# 4 0.0033512 -1 Homotopy it 1 yyyy yyyy nnnn yyyy 8.54459e-06 +# 5 0.00676554 0 yyyy yyyy nnnn yyyy 1.28198e-05 +# 6 0.00676554 -1 Homotopy it 2 yyyy yyyy nnnn yyyy 1.28198e-05 +# 7 0.000607601 0 yyyy yyyy nnnn yyyy 1.70899e-05 +# 8 0.000607601 -1 Homotopy it 3 yyyy yyyy nnnn yyyy 1.70899e-05 +# 9 0.00254206 0 yyyy yyyy nnnn yyyy 2.13608e-05 +# 10 0.00254206 -1 Homotopy it 4 yyyy yyyy nnnn yyyy 2.13608e-05 +# 11 0.00127848 0 yyyy yyyy nnnn yyyy 2.56333e-05 +# 12 0.00127848 -1 Homotopy it 5 yyyy yyyy nnnn yyyy 2.56333e-05 +# 13 0.000285469 0 yyyy yyyy nnnn yyyy 2.99055e-05 +# 14 0.000285469 -1 Homotopy it 6 yyyy yyyy nnnn yyyy 2.99055e-05 +# 15 0.00366699 0 yyyy yyyy nnnn yyyy 3.41767e-05 +# 16 0.00366699 -1 Homotopy it 7 yyyy yyyy nnnn yyyy 3.41767e-05 +# 17 0.00158214 0 yyyy yyyy nnnn yyyy 3.84465e-05 +# 18 0.00158214 -1 Homotopy it 8 yyyy yyyy nnnn yyyy 3.84465e-05 +# 19 0.00353517 0 yyyy yyyy nnnn yyyy 4.2715e-05 +# 20 0.00353517 -1 Homotopy it 9 yyyy yyyy nnnn yyyy 4.2715e-05 + +# Inspect optimization outcome +opt.target_status() +opt.vary_status() +# prints: +# +# Target status: +# id state tag tol_met residue current_val target_val description +# 0 ON tune True 8.53717e-11 62.315 62.315 'qx', val=62.315, tol=1e-06, weight=10) +# 1 ON tune True 1.49214e-13 60.325 60.325 'qy', val=60.325, tol=1e-06, weight=10) +# 2 ON chrom True 1.22005e-06 10 10 'dqx', val=10, tol=0.01, weight=1) +# 3 ON chrom True -1.87538e-09 12 12 'dqy', val=12, tol=0.01, weight=1) +# Vary status: +# id state tag name lower_limit current_val upper_limit val_at_iter_0 step weight +# 0 ON quad kqtf.b1 None 4.27163e-05 None 0 1e-08 1 +# 1 ON quad kqtd.b1 None -4.27199e-05 None 0 1e-08 1 +# 2 ON sext ksf.b1 -0.1 0.0118965 0.1 0 0.0001 1 +# 3 ON sext ksd.b1 -0.1 -0.0232137 0.1 0 0.0001 1 + +# Get knob values after optimization +knobs_after_match = opt.get_knob_values() +# contains: {'kqtf.b1': 4.27163e-05, 'kqtd.b1': -4.27199e-05, +# 'ksf.b1': 0.0118965, 'ksd.b1': -0.0232137} + +# Get knob values before optimization +knobs_before_match = opt.get_knob_values(iteration=0) +# contains: {'kqtf.b1': 0, 'kqtd.b1': 0, 'ksf.b1': 0, 'ksd.b1': 0} + From b5b4a37f9ef04b2c5264ab7c4c5eec8881502af0 Mon Sep 17 00:00:00 2001 From: Bernardo Abreu Figueiredo Date: Wed, 11 Sep 2024 11:23:06 +0200 Subject: [PATCH 2/5] added homotopy test (without testing subtargets) --- tests/test_match_tune_chroma_cminus.py | 62 ++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/tests/test_match_tune_chroma_cminus.py b/tests/test_match_tune_chroma_cminus.py index 7fbaf032a..da655986e 100644 --- a/tests/test_match_tune_chroma_cminus.py +++ b/tests/test_match_tune_chroma_cminus.py @@ -6,6 +6,7 @@ import xpart as xp import xtrack as xt from xobjects.test_helpers import for_all_test_contexts +import numpy as np test_data_folder = pathlib.Path( __file__).parent.joinpath('../test_data').absolute() @@ -130,6 +131,67 @@ def test_match_tune_chromaticity(test_context): xo.assert_allclose(tw_final['dqx'], 6.0, atol=0.05) xo.assert_allclose(tw_final['dqy'], 4.0, atol=0.05) +@for_all_test_contexts +def test_match_tune_chromaticity_homotopy(test_context): + + with open(path_line) as f: + dct = json.load(f) + + line = xt.Line.from_dict(dct['line']) + line.particle_ref = xp.Particles.from_dict(dct['particle']) + + line.build_tracker(_context=test_context) + + print('\nInitial twiss parameters') + tw_before = line.twiss() + print(f"Qx = {tw_before['qx']:.5f} Qy = {tw_before['qy']:.5f} " + f"Q'x = {tw_before['dqx']:.5f} Q'y = {tw_before['dqy']:.5f}") + + print(f"kqtf.b1 = {line.vars['kqtf.b1']._value}") + print(f"kqtd.b1 = {line.vars['kqtd.b1']._value}") + print(f"ksf.b1 = {line.vars['ksf.b1']._value}") + print(f"ksd.b1 = {line.vars['ksd.b1']._value}") + + t1 = time.time() + opt = line.match( + solve=False, + vary=[ + xt.Vary('kqtf.b1', step=1e-8), + xt.Vary('kqtd.b1', step=1e-8), + xt.Vary('ksf.b1', step=1e-8), + xt.Vary('ksd.b1', step=1e-8), + ], + targets = [ + xt.Target('qx', 62.315, tol=1e-4), + xt.Target(lambda tw: tw['qx'] - tw['qy'], 1.99, tol=1e-4), + xt.Target('dqx', 10.0, tol=0.05), + xt.Target('dqy', 12.0, tol=0.05)]) + opt.solve_homotopy() + t2 = time.time() + print('\nTime fsolve: ', t2-t1) + + tw_final = line.twiss() + print('\nFinal twiss parameters') + print(f"Qx = {tw_final['qx']:.5f} Qy = {tw_final['qy']:.5f} " + f"Q'x = {tw_final['dqx']:.5f} Q'y = {tw_final['dqy']:.5f}") + print(f"kqtf.b1 = {line.vars['kqtf.b1']._value}") + print(f"kqtd.b1 = {line.vars['kqtd.b1']._value}") + print(f"ksf.b1 = {line.vars['ksf.b1']._value}") + print(f"ksd.b1 = {line.vars['ksd.b1']._value}") + + xo.assert_allclose(tw_final['qx'], 62.315, atol=1e-7) + xo.assert_allclose(tw_final['qy'], 60.325, atol=1e-7) + xo.assert_allclose(tw_final['dqx'], 10.0, atol=0.05) + xo.assert_allclose(tw_final['dqy'], 12.0, atol=0.05) + + # Assert that Homotopy arrays were created accordingly + qx = np.linspace(tw_before['qx'], 62.315, 11)[1:] + qy = np.linspace(tw_before['qy'], 60.325, 11)[1:] + dqx = np.linspace(tw_before['dqx'], 10.0, 11)[1:] + dqy = np.linspace(tw_before['dqy'], 12.0, 11)[1:] + + # Targets are not logged (only reached values when solving), so no test if they match + @for_all_test_contexts def test_match_coupling(test_context): From da14faf63bf3ae6f3891d1867e433ab3df9b8080 Mon Sep 17 00:00:00 2001 From: Bernardo Abreu Figueiredo Date: Wed, 11 Sep 2024 15:39:01 +0200 Subject: [PATCH 3/5] Added assertion for number of steps in log and homotopy entries --- tests/test_match_tune_chroma_cminus.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/tests/test_match_tune_chroma_cminus.py b/tests/test_match_tune_chroma_cminus.py index da655986e..ccdf019a7 100644 --- a/tests/test_match_tune_chroma_cminus.py +++ b/tests/test_match_tune_chroma_cminus.py @@ -184,13 +184,12 @@ def test_match_tune_chromaticity_homotopy(test_context): xo.assert_allclose(tw_final['dqx'], 10.0, atol=0.05) xo.assert_allclose(tw_final['dqy'], 12.0, atol=0.05) - # Assert that Homotopy arrays were created accordingly - qx = np.linspace(tw_before['qx'], 62.315, 11)[1:] - qy = np.linspace(tw_before['qy'], 60.325, 11)[1:] - dqx = np.linspace(tw_before['dqx'], 10.0, 11)[1:] - dqy = np.linspace(tw_before['dqy'], 12.0, 11)[1:] - - # Targets are not logged (only reached values when solving), so no test if they match + # Order of steps in log + assert len(opt._log['tag']) < 25 + + # Look that Homotopy exists + for i in range(10): + assert f'Homotopy it {i}' in opt._log['tag'] @for_all_test_contexts From c29576b0bb5e202d36f6fed0265d536ed9de6ef2 Mon Sep 17 00:00:00 2001 From: Bernardo Abreu Figueiredo Date: Wed, 11 Sep 2024 15:39:01 +0200 Subject: [PATCH 4/5] Added assertion for number of steps in log and homotopy entries --- tests/test_match_tune_chroma_cminus.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_match_tune_chroma_cminus.py b/tests/test_match_tune_chroma_cminus.py index ccdf019a7..99a8df329 100644 --- a/tests/test_match_tune_chroma_cminus.py +++ b/tests/test_match_tune_chroma_cminus.py @@ -184,10 +184,10 @@ def test_match_tune_chromaticity_homotopy(test_context): xo.assert_allclose(tw_final['dqx'], 10.0, atol=0.05) xo.assert_allclose(tw_final['dqy'], 12.0, atol=0.05) - # Order of steps in log + # Assure reasonable number of steps in log assert len(opt._log['tag']) < 25 - # Look that Homotopy exists + # Look that Homotopy entries exist in the log for i in range(10): assert f'Homotopy it {i}' in opt._log['tag'] From 0b618f5bae6834377feeb5e235d855c1dc82b72a Mon Sep 17 00:00:00 2001 From: Bernardo Abreu Figueiredo Date: Wed, 11 Sep 2024 15:51:23 +0200 Subject: [PATCH 5/5] removed unused imports --- examples/match/000_match_basic_homotopy.py | 2 -- tests/test_match_tune_chroma_cminus.py | 1 - 2 files changed, 3 deletions(-) diff --git a/examples/match/000_match_basic_homotopy.py b/examples/match/000_match_basic_homotopy.py index 35b054d93..905f6fa45 100644 --- a/examples/match/000_match_basic_homotopy.py +++ b/examples/match/000_match_basic_homotopy.py @@ -1,6 +1,4 @@ import xtrack as xt -import matplotlib.pyplot as plt -import numpy as np # Load a line and build a tracker line = xt.Line.from_json('../../test_data/hllhc15_thick/lhc_thick_with_knobs.json') diff --git a/tests/test_match_tune_chroma_cminus.py b/tests/test_match_tune_chroma_cminus.py index 99a8df329..b25ad5dc4 100644 --- a/tests/test_match_tune_chroma_cminus.py +++ b/tests/test_match_tune_chroma_cminus.py @@ -6,7 +6,6 @@ import xpart as xp import xtrack as xt from xobjects.test_helpers import for_all_test_contexts -import numpy as np test_data_folder = pathlib.Path( __file__).parent.joinpath('../test_data').absolute()