{ "cells": [ { "cell_type": "markdown", "id": "6ab1440e", "metadata": {}, "source": [ "# Improving simulation performance\n", "\n", "After defining an SCFT/FTS system, you may notice that your system is difficult to converge or equilibrate. Separately, you may also need your system to finish simulating as quickly as possible. For both of these scenarios the field updater parameters ($\\Delta t$, $\\{ \\lambda_1, \\lambda_2, ..., \\lambda_n\\}$) need to be correctly chosen, and OpenFTS offers an effective approach to choose them via **timestep optimization**. In this tutorial, you will learn how to perform timestep optimization using the TimestepOptimizer class and its three different search methods.\n", "\n", "## Optimizing a 1D system with GridSearch\n", "\n", "First let's define a diblock melt system which we want to simulate with SCFT." ] }, { "cell_type": "code", "execution_count": 1, "id": "6f1a0a96", "metadata": {}, "outputs": [], "source": [ "import openfts\n", "\n", "# Initialize an OpenFTS object. \n", "fts = openfts.OpenFTS()\n", "\n", "# Define the runtime mode, simulation cell, and field updater/layout. \n", "fts.runtime_mode('serial') # Run on CPU.\n", "fts.cell(cell_scale=1.0, cell_lengths=[4.73846], dimension=1, length_unit='Rg') \n", "fts.driver(dt=1.0, nsteps=1000, output_freq=250, stop_tolerance=1e-5, type='SCFT') \n", "fts.field_updater(type='EMPEC', update_order='simultaneous', \n", " adaptive_timestep=False, lambdas=[1.0, 1.0]) \n", "fts.field_layout(npw=[32], random_seed=1)\n", "\n", "# Define the diblock blend model.\n", "fts.model(Nref=50, bref=1.0, chi_array=[0.8], inverse_BC=1/20, type='MeltChiMultiSpecies') \n", "fts.add_molecule(nbeads=50, nblocks=2, block_fractions=[0.5, 0.5], \n", " block_species=['A', 'B'], type='PolymerLinear', \n", " chain_type='discrete', volume_frac=1.0) \n", "fts.add_species(label='A', stat_segment_length=1.0, smearing_length=0.15,\n", " smearing_length_units='Rg') \n", "fts.add_species(label='B', stat_segment_length=1.0, smearing_length=0.15,\n", " smearing_length_units='Rg')\n", "\n", "# Initialize the fields as phase separated.\n", "fts.init_model_field(type='gaussians', height=1.0, ngaussian=1, width=0.1, \n", " centers=[0], fieldname='mu_1') \n", "fts.init_model_field(type='random', mean=0.0, stdev=1, fieldname='mu_2')\n", "\n", "# Output the Hamiltonian and use default output names.\n", "fts.add_operator(averaging_type='none', type='Hamiltonian')\n", "fts.output_default()" ] }, { "cell_type": "markdown", "id": "0c34c76b", "metadata": {}, "source": [ "This system microphase separates to form a lamellar phase with a unit cell length of about $4.74 \\: R_g$, and if we run a copy of this system with the trivial field updater parameters of $\\Delta t = \\lambda_1 = \\lambda_2 = 1.0$ we get the following outcome:" ] }, { "cell_type": "code", "execution_count": 2, "id": "012d6dba", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "================================================================\n", " OpenFTS \n", "\n", "OpenFTS version: heads/develop 7fd5b64 DIRTY\n", "FieldLib version: remotes/origin/HEAD 9ce5644 CLEAN\n", "Execution device: [CPU]\n", "FieldLib precision: double\n", "Licensee: Andrew Golembeski | aag99@drexel.edu | Expiration: 12/31/24\n", "================================================================\n", "\n", "Setup Species\n", " * label = A\n", " * stat_segment_length (b) = 1\n", " * smearing_length (a) = 0.15\n", " * smearing_length_units = Rg\n", " * charge = 0.000000\n", "Setup Species\n", " * label = B\n", " * stat_segment_length (b) = 1\n", " * smearing_length (a) = 0.15\n", " * smearing_length_units = Rg\n", " * charge = 0.000000\n", "Initialize Cell\n", " * dim = 1\n", " * length unit = Rg\n", " * cell_lengths = [4.738460 ]\n", " * cell_tensor: \n", "4.73846\n", "Initialize FieldLayout\n", " * npw = [32 ]\n", " * random_seed = 1\n", "Setup MoleculePolymerLinear\n", " * chain_type = discrete\n", "Setup ModelMeltChiMultiSpecies\n", " * bref = 1\n", " * Nref = 50\n", " * C = UNSPECIFIED\n", " * rho0 = UNSPECIFIED\n", " * chiN_matrix = \n", " 0 40\n", "40 0\n", " * compressibility_type = exclvolume\n", " * inverse_BC = 0.05\n", " * X_matrix = \n", "[[4.47213595499958, 13.4164078649987],\n", " [13.4164078649987, 4.47213595499958]]\n", " * O_matrix (cols are eigenvectors) = \n", "-0.707107 0.707107\n", " 0.707107 0.707107\n", " * d_i = -8.94427191 17.88854382 \n", "Initialize MoleculePolymerLinear\n", " * Linear polymer has single chain: \n", " - type = discrete\n", " - nbeads = 50\n", " - discrete_type = Gaussian\n", " - sequence_type = blocks\n", " - nblocks = 2\n", " - block_fractions = 0.500000 0.500000\n", " - block_species = A B\n", " - monomer_sequence (compact) = A_25 B_25\n", " - monomer_sequence (long) = AAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBB\n", " - species_fractions = 0.5 0.5\n", " * volume_frac = 1\n", " * ncopies = UNDEFINED (since C undefined)\n", "Initialize ModelMeltChiMultiSpecies\n", " * C/rho0 unspecified and all molecules specify volume_frac -> C/rho0 remain undefined (OK for SCFT).\n", " * exchange_field_names = 'mu_1' 'mu_2' \n", " * initfields = yes\n", " - set mu_1 as exchange field using gaussians\n", " - set mu_2 as exchange field using random 0+/-1\n", "Initialize DriverSCFTCL\n", " * is_complex_langevin = false\n", " * dt = 1\n", " * output_freq = 250\n", " * output_fields_freq = 250\n", " * block_size = 250\n", " * field_updater = EMPEC\n", " - predictor_corrector = true\n", " - update_order = simultaneous\n", " - lambdas = 1.000000 1.000000 \n", " - adaptive_timestep = false\n", "\n", " * field_stop_tolerance = 1e-05\n", "Calculating Operators:\n", " * OperatorHamiltonian\n", " - type = scalar\n", " - averaging_type = none\n", " - save_history = true\n", "Output to files: \n", " * scalar_operators -> \"operators.dat\"\n", " * species_densities -> \"density.dat\"\n", " -> save_history = false\n", " * exchange_fields -> \"fields.dat\"\n", " -> save_history = false\n", " * field_errors -> \"error.dat\"\n", "\n", "Running DriverSCFTCL\n", " * nsteps = 1000\n", " * resume = false\n", " * store_operator_timeseries = true\n", "\n", "Starting Run.\n", "Step: 1 H: 3.770749e-01 +0.000e+00i FieldErr: 7.25e-01 TPS: 1470.21\n", "Step: 250 H: 1.533078e+01 +0.000e+00i FieldErr: 3.90e-02 TPS: 9903.94\n", "Step: 500 H: 1.536908e+01 +0.000e+00i FieldErr: 2.24e-03 TPS: 10887.25\n", "Step: 750 H: 1.536916e+01 +0.000e+00i FieldErr: 9.72e-05 TPS: 10609.34\n", "SCFT converged in 932 steps to tolerance: 0.00 (fields)\n", "* H = 15.3692 +0i\n", "Run completed in 0.09 seconds (10289.30 steps / sec).\n" ] } ], "source": [ "import copy\n", "fts_tmp = copy.deepcopy(fts)\n", "fts_tmp.run()" ] }, { "cell_type": "markdown", "id": "88c92c11", "metadata": {}, "source": [ "where we find that the system converges in 932 steps. Suppose we want to converge the system within 100 steps. Increasing $\\Delta t$, $\\lambda_1$, or $\\lambda_2$ will increase the magnitude of the field updates at every timestep, which generally results in faster convergence. However, if this magnitude is too great then the simulation will not converge. To find the largest magnitude possible, we can use the **GridSearch** search method of TimestepOptimizer." ] }, { "cell_type": "code", "execution_count": 3, "id": "6327919e", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Performing timestep optimization using GridSearch\n", "Evaluating lambdas 1600 / 1600\n", "TimestepOptimizer took 0.36 minutes in total\n", "Optimal timestep: 1.0\n", "Optimal lambdas: [34.55, 30.7]\n" ] } ], "source": [ "# Initialize a TimestepOptimizer object.\n", "optimizer = openfts.TimestepOptimizer(fts)\n", "\n", "# Set TimestepOptimizer's search method along with the method's keyword arguments.\n", "optimizer.set_search_method('GridSearch', min_lambda=1.0, max_lambda=100.0, \n", " points_per_lambda=40)\n", "\n", "# Run TimestepOptimizer's search method parallelized over 12 processes with high verbosity.\n", "optimizer.run(nprocs=12, verbosity=2)" ] }, { "cell_type": "markdown", "id": "6fe45b20", "metadata": {}, "source": [ "GridSearch first creates a grid of different $\\left(\\lambda_1, \\lambda_2\\right)$'s with $\\Delta t$ held constant, and then evaluates each grid point. While this method can be computationally expensive, it is comprehensive. If we visualize the results of the search:" ] }, { "cell_type": "code", "execution_count": 4, "id": "70d28feb", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "optimizer.plot_results()" ] }, { "cell_type": "markdown", "id": "17d902df", "metadata": {}, "source": [ "we can easily access the performance of the grid points evaluated. Gray-colored points did not converge before reaching the maximum number of steps (here 1000) and black-colored points diverged. We therefore have found many $\\left(\\Delta t, \\lambda_1, \\lambda_2\\right)$ which converge within 100 steps, meeting our goal! Through our search, we found the best field updater parameters to be $\\Delta t = 1.0$, $\\lambda_1 = 34.55$, $\\lambda_2 = 30.70$ which converges in 32 steps. Since each $\\lambda_i$ is multiplied by $\\Delta t$ in the field updater equation, this optimum is also equivalent to $\\Delta t = 10.0$, $\\lambda_1 = 3.455$, $\\lambda_2 = 3.070$." ] }, { "cell_type": "markdown", "id": "395591a1", "metadata": {}, "source": [ "## Optimizing a 3D system with ManualSearch\n", "\n", "Suppose now we want to optimize the previous system but instead it is 3D instead of 1D. We can use GridSearch again but now it will take significantly longer as 3D simulations have a higher computational cost. Because corresponding 1D and 3D SCFT systems can have similar performance under the same field updater parameters, another approach is to try the top 100 $\\left(\\lambda_1, \\lambda_2\\right)$'s of the 1D system in the 3D system with $\\Delta t$ held constant. We can perform this by using the **ManualSearch** search method. First, let's create a file containing the top 100 $\\left(\\lambda_1, \\lambda_2\\right)$'s to evaluate." ] }, { "cell_type": "code", "execution_count": 5, "id": "7b3566e5", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "\n", "# Get the lambdas evaluated and their performance as numpy arrays.\n", "lambdas, performance, outcome, operators = optimizer.get_results()\n", "lambdas = np.asarray(lambdas)\n", "performance = np.asarray(performance)\n", "\n", "# Get the top 100 lambdas (in order)\n", "sort_indices = np.argsort(performance)\n", "top_100_lambdas = lambdas[sort_indices[:100]]\n", "\n", "# Write the top 100 lambdas to a file.\n", "with open('lambdas.dat', 'w') as f:\n", " f.write('# Lambdas for ManualSearch.\\n')\n", " for lam in top_100_lambdas:\n", " f.write(f'{lam[0]} {lam[1]}\\n')" ] }, { "cell_type": "markdown", "id": "167262d0", "metadata": {}, "source": [ "Now let's define our 3D system and perform ManualSearch using these $\\left(\\lambda_1, \\lambda_2\\right)$'s. For 3D OpenFTS systems, running on a GPU greatly increases the speed of the simulation but let's assume we only have access to a CPU. Let's also assume that our goal is to find a simulation that can converge within 250 steps." ] }, { "cell_type": "code", "execution_count": 6, "id": "981bda98", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Performing timestep optimization using ManualSearch\n", "Evaluating lambdas 100 / 100\n", "TimestepOptimizer took 9.63 minutes in total\n", "Optimal timestep: 1.0\n", "Optimal lambdas: [30.7, 27.28]\n" ] } ], "source": [ "# Create a copy of the 1D SCFT system.\n", "fts_3D = copy.deepcopy(fts)\n", "\n", "# Convert the copy to a 3D SCFT system.\n", "fts_3D.params['cell']['cell_lengths'] = 3*[4.73846]\n", "fts_3D.params['cell']['tilt_factors'] = 3*[0]\n", "fts_3D.params['cell']['dimension'] = 3\n", "fts_3D.params['fieldlayout']['npw'] = 3*[32]\n", "fts_3D.params['model']['initfields']['mu_1']['center0'] = 3*[0]\n", "\n", "# Change the maximum number of steps.\n", "fts_3D.params['driver']['nsteps'] = 250\n", "\n", "# Initialize a TimestepOptimizer object.\n", "optimizer = openfts.TimestepOptimizer(fts_3D)\n", "\n", "# Set TimestepOptimizer's search method along with the method's keyword arguments.\n", "optimizer.set_search_method('ManualSearch', lambdas_file='lambdas.dat')\n", "\n", "# Run TimestepOptimizer's search method parallelized over 12 processes with high verbosity.\n", "optimizer.run(nprocs=12, verbosity=2)" ] }, { "cell_type": "markdown", "id": "a362c41d", "metadata": {}, "source": [ "With ManualSearch, we reached our goal by finding that $\\Delta t = 1.0$, $\\lambda_1 = 30.70$, $\\lambda_2 = 27.28$ converges the 3D system within 250 steps. We can also clearly see how much longer 3D systems take to simulate than 1D systems on CPUs. Evaluating 100 $\\left(\\lambda_1, \\lambda_2\\right)$'s in the 3D system took us a little less than 10 minutes, while evaluating 1600 $\\left(\\lambda_1, \\lambda_2\\right)$'s in the 1D system only took us roughly a third of a minute." ] }, { "cell_type": "markdown", "id": "d461432e", "metadata": {}, "source": [ "## Simulating a difficult system with BayesOptSearch\n", "Occasionally you may find an OpenFTS system which does not converge or equilibrate with trivial field updater parameters. One such system is a homopolymer blend which undergoes macrophase separation, as defined below." ] }, { "cell_type": "code", "execution_count": 7, "id": "d1653873", "metadata": {}, "outputs": [], "source": [ "# Initialize an OpenFTS object. \n", "fts = openfts.OpenFTS()\n", "\n", "# Define the runtime mode, simulation cell, and field updater/layout. \n", "fts.runtime_mode('serial') # Run on CPU.\n", "fts.cell(cell_scale=1.0, cell_lengths=[4.0], dimension=1, length_unit='Rg') \n", "fts.driver(dt=0.5, nsteps=1000, output_freq=250, stop_tolerance=1e-5, type='SCFT') \n", "fts.field_updater(type='EMPEC', update_order='simultaneous', \n", " adaptive_timestep=False, lambdas=[1.0, 1.0]) \n", "fts.field_layout(npw=[32], random_seed=1)\n", "\n", "# Define the homopolymer blend model.\n", "fts.model(Nref=100, bref=1.0, chi_array=[0.8], inverse_BC=1/100, type='MeltChiMultiSpecies') \n", "fts.add_molecule(nbeads=100, nblocks=1, block_fractions=[1.0], \n", " block_species=['A'], type='PolymerLinear', \n", " chain_type='discrete', volume_frac=0.5) \n", "fts.add_molecule(nbeads=100, nblocks=1, block_fractions=[1.0], \n", " block_species=['B'], type='PolymerLinear', \n", " chain_type='discrete', volume_frac=0.5)\n", "fts.add_species(label='A', stat_segment_length=1.0, smearing_length=0.15,\n", " smearing_length_units='Rg') \n", "fts.add_species(label='B', stat_segment_length=1.0, smearing_length=0.15,\n", " smearing_length_units='Rg')\n", "\n", "# Initialize the fields as phase separated.\n", "fts.init_model_field(type='gaussians', height=1.0, ngaussian=1, width=0.1, \n", " centers=[0], fieldname='mu_1') \n", "fts.init_model_field(type='random', mean=0.0, stdev=1, fieldname='mu_2')\n", "\n", "# Output the Hamiltonian and use default output names.\n", "fts.add_operator(averaging_type='none', type='Hamiltonian')\n", "fts.output_default()" ] }, { "cell_type": "markdown", "id": "7ad42011", "metadata": {}, "source": [ "We can see that this system does not converge even if we increase the maximum number of steps by a factor of 10:" ] }, { "cell_type": "code", "execution_count": 8, "id": "415d8422", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "================================================================\n", " OpenFTS \n", "\n", "OpenFTS version: heads/develop 7fd5b64 DIRTY\n", "FieldLib version: remotes/origin/HEAD 9ce5644 CLEAN\n", "Execution device: [CPU]\n", "FieldLib precision: double\n", "Licensee: Andrew Golembeski | aag99@drexel.edu | Expiration: 12/31/24\n", "================================================================\n", "\n", "Setup Species\n", " * label = A\n", " * stat_segment_length (b) = 1\n", " * smearing_length (a) = 0.15\n", " * smearing_length_units = Rg\n", " * charge = 0.000000\n", "Setup Species\n", " * label = B\n", " * stat_segment_length (b) = 1\n", " * smearing_length (a) = 0.15\n", " * smearing_length_units = Rg\n", " * charge = 0.000000\n", "Initialize Cell\n", " * dim = 1\n", " * length unit = Rg\n", " * cell_lengths = [4.000000 ]\n", " * cell_tensor: \n", "4\n", "Initialize FieldLayout\n", " * npw = [32 ]\n", " * random_seed = 1\n", "Setup MoleculePolymerLinear\n", " * chain_type = discrete\n", "Setup MoleculePolymerLinear\n", " * chain_type = discrete\n", "Setup ModelMeltChiMultiSpecies\n", " * bref = 1\n", " * Nref = 100\n", " * C = UNSPECIFIED\n", " * rho0 = UNSPECIFIED\n", " * chiN_matrix = \n", " 0 80\n", "80 0\n", " * compressibility_type = exclvolume\n", " * inverse_BC = 0.01\n", " * X_matrix = \n", "[[10, 18],\n", " [18, 10]]\n", " * O_matrix (cols are eigenvectors) = \n", "-0.707107 0.707107\n", " 0.707107 0.707107\n", " * d_i = -8 28 \n", "Initialize MoleculePolymerLinear\n", " * Linear polymer has single chain: \n", " - type = discrete\n", " - nbeads = 100\n", " - discrete_type = Gaussian\n", " - sequence_type = blocks\n", " - nblocks = 1\n", " - block_fractions = 1.000000\n", " - block_species = A\n", " - monomer_sequence (compact) = A_100\n", " - monomer_sequence (long) = AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\n", " - species_fractions = 1 0\n", " * volume_frac = 0.5\n", " * ncopies = UNDEFINED (since C undefined)\n", "Initialize MoleculePolymerLinear\n", " * Linear polymer has single chain: \n", " - type = discrete\n", " - nbeads = 100\n", " - discrete_type = Gaussian\n", " - sequence_type = blocks\n", " - nblocks = 1\n", " - block_fractions = 1.000000\n", " - block_species = B\n", " - monomer_sequence (compact) = B_100\n", " - monomer_sequence (long) = BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB\n", " - species_fractions = 0 1\n", " * volume_frac = 0.5\n", " * ncopies = UNDEFINED (since C undefined)\n", "Initialize ModelMeltChiMultiSpecies\n", " * C/rho0 unspecified and all molecules specify volume_frac -> C/rho0 remain undefined (OK for SCFT).\n", " * exchange_field_names = 'mu_1' 'mu_2' \n", " * initfields = yes\n", " - set mu_1 as exchange field using gaussians\n", " - set mu_2 as exchange field using random 0+/-1\n", "Initialize DriverSCFTCL\n", " * is_complex_langevin = false\n", " * dt = 0.5\n", " * output_freq = 250\n", " * output_fields_freq = 250\n", " * block_size = 250\n", " * field_updater = EMPEC\n", " - predictor_corrector = true\n", " - update_order = simultaneous\n", " - lambdas = 1.000000 1.000000 \n", " - adaptive_timestep = false\n", "\n", " * field_stop_tolerance = 1e-05\n", "Calculating Operators:\n", " * OperatorHamiltonian\n", " - type = scalar\n", " - averaging_type = none\n", " - save_history = true\n", "Output to files: \n", " * scalar_operators -> \"operators.dat\"\n", " * species_densities -> \"density.dat\"\n", " -> save_history = false\n", " * exchange_fields -> \"fields.dat\"\n", " -> save_history = false\n", " * field_errors -> \"error.dat\"\n", "\n", "Running DriverSCFTCL\n", " * nsteps = 10000\n", " * resume = false\n", " * store_operator_timeseries = true\n", "\n", "Starting Run.\n", "Step: 1 H: 1.218931e-01 +0.000e+00i FieldErr: 7.69e-01 TPS: 1124.29\n", "Step: 250 H: 2.735070e+01 +0.000e+00i FieldErr: 5.99e-01 TPS: 2504.39\n", "Step: 500 H: 4.361468e+01 +0.000e+00i FieldErr: 3.21e-01 TPS: 3042.24\n", "Step: 750 H: 5.059678e+01 +0.000e+00i FieldErr: 1.99e-01 TPS: 3047.10\n", "Step: 1000 H: 5.344081e+01 +0.000e+00i FieldErr: 1.34e-01 TPS: 2965.97\n", "Step: 1250 H: 5.459605e+01 +0.000e+00i FieldErr: 1.16e-01 TPS: 2938.48\n", "Step: 1500 H: 5.496282e+01 +0.000e+00i FieldErr: 3.30e-01 TPS: 3001.85\n", "Step: 1750 H: 5.527022e+01 +0.000e+00i FieldErr: 2.97e-01 TPS: 2971.07\n", "Step: 2000 H: 5.516744e+01 +0.000e+00i FieldErr: 5.73e-01 TPS: 2997.15\n", "Step: 2250 H: 5.519802e+01 +0.000e+00i FieldErr: 6.51e-01 TPS: 3057.75\n", "Step: 2500 H: 5.459357e+01 +0.000e+00i FieldErr: 7.41e-01 TPS: 3036.02\n", "Step: 2750 H: 5.539947e+01 +0.000e+00i FieldErr: 3.59e-01 TPS: 3008.34\n", "Step: 3000 H: 5.605426e+01 +0.000e+00i FieldErr: 4.18e-01 TPS: 3039.67\n", "Step: 3250 H: 5.578217e+01 +0.000e+00i FieldErr: 6.22e-01 TPS: 3058.59\n", "Step: 3500 H: 5.473688e+01 +0.000e+00i FieldErr: 7.91e-01 TPS: 2977.01\n", "Step: 3750 H: 5.453012e+01 +0.000e+00i FieldErr: 7.67e-01 TPS: 3037.10\n", "Step: 4000 H: 5.568272e+01 +0.000e+00i FieldErr: 3.19e-01 TPS: 3061.68\n", "Step: 4250 H: 5.611712e+01 +0.000e+00i FieldErr: 4.96e-01 TPS: 3062.00\n", "Step: 4500 H: 5.550964e+01 +0.000e+00i FieldErr: 6.80e-01 TPS: 2995.57\n", "Step: 4750 H: 5.447476e+01 +0.000e+00i FieldErr: 8.25e-01 TPS: 3065.51\n", "Step: 5000 H: 5.483648e+01 +0.000e+00i FieldErr: 6.37e-01 TPS: 3017.43\n", "Step: 5250 H: 5.592160e+01 +0.000e+00i FieldErr: 3.32e-01 TPS: 2945.99\n", "Step: 5500 H: 5.604256e+01 +0.000e+00i FieldErr: 5.61e-01 TPS: 2911.80\n", "Step: 5750 H: 5.518283e+01 +0.000e+00i FieldErr: 7.30e-01 TPS: 3017.41\n", "Step: 6000 H: 5.436067e+01 +0.000e+00i FieldErr: 8.39e-01 TPS: 2999.43\n", "Step: 6250 H: 5.522179e+01 +0.000e+00i FieldErr: 4.40e-01 TPS: 3008.42\n", "Step: 6500 H: 5.606547e+01 +0.000e+00i FieldErr: 4.04e-01 TPS: 2998.76\n", "Step: 6750 H: 5.587658e+01 +0.000e+00i FieldErr: 6.12e-01 TPS: 3045.76\n", "Step: 7000 H: 5.484573e+01 +0.000e+00i FieldErr: 7.76e-01 TPS: 3087.82\n", "Step: 7250 H: 5.443600e+01 +0.000e+00i FieldErr: 8.10e-01 TPS: 3034.33\n", "Step: 7500 H: 5.557367e+01 +0.000e+00i FieldErr: 3.37e-01 TPS: 2976.39\n", "Step: 7750 H: 5.611922e+01 +0.000e+00i FieldErr: 4.75e-01 TPS: 3041.38\n", "Step: 8000 H: 5.562699e+01 +0.000e+00i FieldErr: 6.58e-01 TPS: 3059.83\n", "Step: 8250 H: 5.455745e+01 +0.000e+00i FieldErr: 8.17e-01 TPS: 2994.06\n", "Step: 8500 H: 5.469776e+01 +0.000e+00i FieldErr: 7.07e-01 TPS: 3028.65\n", "Step: 8750 H: 5.584267e+01 +0.000e+00i FieldErr: 3.22e-01 TPS: 3018.73\n", "Step: 9000 H: 5.608152e+01 +0.000e+00i FieldErr: 5.40e-01 TPS: 2981.95\n", "Step: 9250 H: 5.531412e+01 +0.000e+00i FieldErr: 7.08e-01 TPS: 3032.14\n", "Step: 9500 H: 5.438383e+01 +0.000e+00i FieldErr: 8.42e-01 TPS: 3048.54\n", "Step: 9750 H: 5.507128e+01 +0.000e+00i FieldErr: 5.21e-01 TPS: 3048.05\n", "Step: 10000 H: 5.602076e+01 +0.000e+00i FieldErr: 3.74e-01 TPS: 2954.09\n", "Run reached specified number of steps\n", "Run completed in 3.34 seconds (2998.39 steps / sec).\n" ] } ], "source": [ "fts_tmp = copy.deepcopy(fts)\n", "fts_tmp.params['driver']['nsteps'] *= 10\n", "fts_tmp.run()" ] }, { "cell_type": "markdown", "id": "f0412f0c", "metadata": {}, "source": [ "and we find that the FieldErr is consistently fluctuating above 1e-01. In this scenario, our priority is converging the system and not the speed of convergence. Since we don't need the costly comprehensive power of GridSearch and we don't have any insightful guesses for ManualSearch, guessing field updater parameters in a statistically meaningful way is the next best strategy. This can be done with **BayesOptSearch** which uses Bayesian optimization to efficiently guess $\\left(\\lambda_1, \\lambda_2\\right)$'s." ] }, { "cell_type": "code", "execution_count": 9, "id": "d2691674", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Performing timestep optimization using BayesOptSearch\n", "Evaluating lambdas 200 / 200\n", "TimestepOptimizer took 0.33 minutes in total\n", "Optimal timestep: 0.5\n", "Optimal lambdas: [24.24, 34.55]\n" ] } ], "source": [ "# Initialize a TimestepOptimizer object.\n", "optimizer = openfts.TimestepOptimizer(fts)\n", "\n", "# Set TimestepOptimizer's search method along with the method's keyword arguments.\n", "optimizer.set_search_method('BayesOptSearch', min_lambda=1.0, max_lambda=100.0, \n", " points_per_lambda=40, nlambdas=200)\n", "\n", "# Run TimestepOptimizer's search method parallelized over 12 processes with high verbosity.\n", "optimizer.run(nprocs=12, verbosity=2)" ] }, { "cell_type": "markdown", "id": "834bd8f5", "metadata": {}, "source": [ "Bayesian optimization works by first estimating the means and standard deviations of untried points by using a Gaussian processor regression (GPR) model, and then by acquiring untried points to sample through a so-called aquisition function. The aquisition function naturally seeks high performing points and is well-suited to our scenario. These features can be tuned through the keyword arguments of BayesOptSearch, but importantly let's see how it performed." ] }, { "cell_type": "code", "execution_count": 10, "id": "62c26739", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "optimizer.plot_results()" ] }, { "cell_type": "markdown", "id": "0bce67f1", "metadata": {}, "source": [ "Based on the plot, BayesOptSearch found a few sets of field updater parmeters that converge! We can also see that BayesOptSearch choose most of its points around the best performing $\\left(\\lambda_1, \\lambda_2\\right)$'s. While this completes our task, for curiousity let's see how far off BayesOptSearch was from the global optimum by using GridSearch." ] }, { "cell_type": "code", "execution_count": 11, "id": "a637f4f1", "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Performing timestep optimization using GridSearch\n", "Evaluating lambdas 1600 / 1600\n", "TimestepOptimizer took 1.61 minutes in total\n", "Optimal timestep: 0.5\n", "Optimal lambdas: [27.28, 38.88]\n" ] } ], "source": [ "# Initialize a TimestepOptimizer object.\n", "optimizer = openfts.TimestepOptimizer(fts)\n", "\n", "# Set TimestepOptimizer's search method along with the method's keyword arguments.\n", "optimizer.set_search_method('GridSearch', min_lambda=1.0, max_lambda=100.0, \n", " points_per_lambda=40)\n", "\n", "# Run TimestepOptimizer's search method parallelized over 12 processes with high verbosity.\n", "optimizer.run(nprocs=12, verbosity=2)" ] }, { "cell_type": "code", "execution_count": 12, "id": "4cbf1339", "metadata": {}, "outputs": [ { "data": { "image/png": "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", "text/plain": [ "
" ] }, "metadata": { "needs_background": "light" }, "output_type": "display_data" } ], "source": [ "optimizer.plot_results()" ] }, { "cell_type": "markdown", "id": "a2b381bb", "metadata": {}, "source": [ "Compared to the global optimum, BayesOptSearch found field updater parameters that were slightly slower than GridSearch but in only one fifth of the time. Overall, GridSearch is well preferred when computationally tractable, but BayesOptSearch offers an alternative which can find convergent and performant field updater parameters in significantly less time.\n", "\n", "TimestepOptimizer also offers additional run modifications for the search methods you've learned here. For more information, check out the Timestep Optimization page located under *External Python Tools*." ] } ], "metadata": { "kernelspec": { "display_name": "Python 3 (ipykernel)", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.2" } }, "nbformat": 4, "nbformat_minor": 5 }