mcising 0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
mcising-0.1/PKG-INFO ADDED
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.1
2
+ Name: mcising
3
+ Version: 0.1
4
+ Summary: A package for generating Ising model data using Metropolis algorithm on a square lattice for nearest neighbor and next nearest neighbor interactions.
5
+ Home-page: https://github.com/bcivitcioglu/mcising
6
+ Author: Burak Ç.
7
+ Author-email: bcivitcioglu@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+
13
+ # mcising
14
+
15
+ mcising is a Python package for generating Ising model data using Monte Carlo simulations.
16
+
17
+ ## Installation
18
+
19
+ You can install the package using pip:
20
+
21
+ `pip install mcising`
22
+
23
+ ## Usage
24
+
25
+ You can generate Ising model data from the command line:
26
+
27
+ `generate_ising_data <seed> <lattice_size> <num_configs> <j1> <j2> [--T_init <T_init>] [--T_final <T_final>] [--T_step <T_step>] [--sweep_steps <sweep_steps>] [--thermalization_scans <thermalization_scans>] [--calculate_correlation]`
28
+
29
+ An example usage:
30
+
31
+ `generate_ising_data 42 10 100 1.0 0.5 --T_init 4.0 --T_final 0.1 --T_step 0.05 --sweep_steps 10 --thermalization_scans 5 --calculate_correlation`
32
+
33
+ ## Licence
34
+
35
+ This project is licensed under the MIT License.
mcising-0.1/README.md ADDED
@@ -0,0 +1,23 @@
1
+ # mcising
2
+
3
+ mcising is a Python package for generating Ising model data using Monte Carlo simulations.
4
+
5
+ ## Installation
6
+
7
+ You can install the package using pip:
8
+
9
+ `pip install mcising`
10
+
11
+ ## Usage
12
+
13
+ You can generate Ising model data from the command line:
14
+
15
+ `generate_ising_data <seed> <lattice_size> <num_configs> <j1> <j2> [--T_init <T_init>] [--T_final <T_final>] [--T_step <T_step>] [--sweep_steps <sweep_steps>] [--thermalization_scans <thermalization_scans>] [--calculate_correlation]`
16
+
17
+ An example usage:
18
+
19
+ `generate_ising_data 42 10 100 1.0 0.5 --T_init 4.0 --T_final 0.1 --T_step 0.05 --sweep_steps 10 --thermalization_scans 5 --calculate_correlation`
20
+
21
+ ## Licence
22
+
23
+ This project is licensed under the MIT License.
@@ -0,0 +1,3 @@
1
+ # mcising/__init__.py
2
+ from .isinglattice import IsingLattice
3
+ from .montecarlo import collect_monte_carlo_data
@@ -0,0 +1,44 @@
1
+ # mcising/ising_data_generate.py
2
+
3
+ import numpy as np
4
+ import argparse
5
+ import montecarlo
6
+
7
+ def main(args):
8
+ temperature = np.arange(args.T_init, args.T_final - args.T_step, -args.T_step)
9
+
10
+ montecarlo.collect_monte_carlo_data(
11
+ seed=args.seed,
12
+ lattice_size=args.lattice_size,
13
+ J1=args.j1,
14
+ J2=args.j2,
15
+ h=0.0,
16
+ num_scans=args.sweep_steps * (args.num_configs - 1),
17
+ temperature=temperature,
18
+ thermalization_scans=args.thermalization_scans,
19
+ frequency_sweeps_to_collect_magnetization=args.sweep_steps,
20
+ calculate_correlation=args.calculate_correlation
21
+ )
22
+
23
+ if __name__ == "__main__":
24
+ parser = argparse.ArgumentParser(description="Generate Ising model data using Monte Carlo simulation.")
25
+ parser.add_argument("seed", type=int, help="Random seed for the simulation")
26
+ parser.add_argument("lattice_size", type=int, help="Size of the lattice")
27
+ parser.add_argument("num_configs", type=int, help="Number of configurations to generate")
28
+ parser.add_argument("j1", type=float, help="Interaction parameter J1")
29
+ parser.add_argument("j2", type=float, help="Interaction parameter J2")
30
+ parser.add_argument("--T_init", type=float, default=4.0, help="Initial temperature (default: 4.0)")
31
+ parser.add_argument("--T_final", type=float, default=0.075, help="Final temperature (default: 0.075)")
32
+ parser.add_argument("--T_step", type=float, default=0.025, help="Temperature step (default: 0.025)")
33
+ parser.add_argument("--sweep_steps", type=int, default=1, help="Number of sweep steps (default: 1)")
34
+ parser.add_argument("--thermalization_scans", type=int, default=3, help="Number of thermalization scans (default: 3)")
35
+ parser.add_argument("--calculate_correlation", action="store_true", help="Calculate correlation function and length")
36
+
37
+ args = parser.parse_args()
38
+
39
+ if args.T_step <= 0:
40
+ print("Error: T_step must be greater than 0")
41
+ elif args.T_init <= args.T_final:
42
+ print("Error: T_init must be greater than T_final")
43
+ else:
44
+ main(args)
@@ -0,0 +1,222 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import random
4
+
5
+ class IsingLattice:
6
+ """
7
+ A class to represent an Ising model lattice.
8
+
9
+ Attributes
10
+ ----------
11
+ lattice_size : int
12
+ The size of the lattice.
13
+ num_sites : int
14
+ The total number of sites in the lattice.
15
+ J1 : float
16
+ Interaction parameter for nearest neighbors.
17
+ J2 : float
18
+ Interaction parameter for next nearest neighbors.
19
+ h : float
20
+ External magnetic field.
21
+ lattice_state : np.ndarray
22
+ The state of the lattice.
23
+ """
24
+
25
+ def __init__(self, lattice_size, J1, J2, h):
26
+ """
27
+ Initializes the lattice with random spins.
28
+
29
+ Parameters
30
+ ----------
31
+ lattice_size : int
32
+ The size of the lattice.
33
+ J1 : float
34
+ Interaction parameter for nearest neighbors.
35
+ J2 : float
36
+ Interaction parameter for next nearest neighbors.
37
+ h : float
38
+ External magnetic field.
39
+ """
40
+ self.lattice_size = lattice_size
41
+ self.num_sites = lattice_size * lattice_size
42
+ self.J1 = J1
43
+ self.J2 = J2
44
+ self.h = h
45
+
46
+ # Randomly initialize the lattice with -1 and 1
47
+ lattice_state = np.random.choice([-1, 1], size=(self.lattice_size, self.lattice_size))
48
+ self.lattice_state = lattice_state
49
+
50
+ def plot_lattice(self, print_info=False):
51
+ """
52
+ Plot the current lattice configuration.
53
+
54
+ Parameters
55
+ ----------
56
+ print_info : bool, optional
57
+ If True, prints the lattice information. Default is False.
58
+ """
59
+ plt.figure()
60
+ plt.imshow(self.lattice_state, cmap='gray')
61
+ plt.title("Ising Lattice")
62
+ plt.show()
63
+ if print_info:
64
+ self.print_info()
65
+
66
+ def print_info(self):
67
+ """
68
+ Print information about the lattice.
69
+ """
70
+ print(f"Lattice size: {self.lattice_size} x {self.lattice_size}. J1: {self.J1}, J2: {self.J2}, h: {self.h}")
71
+
72
+ def flip_spin(self, i, j):
73
+ """
74
+ Flip the spin at the given site (i, j).
75
+
76
+ Parameters
77
+ ----------
78
+ i : int
79
+ Row index of the site.
80
+ j : int
81
+ Column index of the site.
82
+ """
83
+ self.lattice_state[i, j] *= -1
84
+
85
+ def spin_energy(self, i, j):
86
+ """
87
+ Calculate the energy of the spin at the given site (i, j).
88
+
89
+ Parameters
90
+ ----------
91
+ i : int
92
+ Row index of the site.
93
+ j : int
94
+ Column index of the site.
95
+
96
+ Returns
97
+ -------
98
+ float
99
+ The energy of the spin at the given site.
100
+ """
101
+ spin_ij = self.lattice_state[i, j]
102
+
103
+ # Periodic boundary conditions
104
+ sum_neighbouring_spins = (
105
+ self.lattice_state[(i + 1) % self.lattice_size, j] +
106
+ self.lattice_state[i, (j + 1) % self.lattice_size] +
107
+ self.lattice_state[(i - 1) % self.lattice_size, j] +
108
+ self.lattice_state[i, (j - 1) % self.lattice_size]
109
+ )
110
+
111
+ sum_second_neighbouring_spins = (
112
+ self.lattice_state[(i + 1) % self.lattice_size, (j + 1) % self.lattice_size] +
113
+ self.lattice_state[(i + 1) % self.lattice_size, (j - 1) % self.lattice_size] +
114
+ self.lattice_state[(i - 1) % self.lattice_size, (j + 1) % self.lattice_size] +
115
+ self.lattice_state[(i - 1) % self.lattice_size, (j - 1) % self.lattice_size]
116
+ )
117
+
118
+ interaction_term = (
119
+ -self.J1 * spin_ij * sum_neighbouring_spins +
120
+ -self.J2 * spin_ij * sum_second_neighbouring_spins
121
+ )
122
+
123
+ if self.h != 0:
124
+ magnetic_field_term = -self.h * spin_ij
125
+ return interaction_term + magnetic_field_term
126
+
127
+ return interaction_term
128
+
129
+ def energy(self):
130
+ """
131
+ Calculate the total energy of the lattice.
132
+
133
+ Returns
134
+ -------
135
+ float
136
+ The total energy of the lattice.
137
+ """
138
+ E = 0.0
139
+ for i in np.arange(self.lattice_size):
140
+ for j in np.arange(self.lattice_size):
141
+ E += self.spin_energy(i, j)
142
+ E /= 2.0 * self.num_sites
143
+ if self.h != 0:
144
+ E -= self.h * np.sum(self.lattice_state) / self.num_sites
145
+ return E
146
+
147
+ def magnetization(self):
148
+ """
149
+ Calculate the net magnetization of the lattice.
150
+
151
+ Returns
152
+ -------
153
+ float
154
+ The net magnetization of the lattice.
155
+ """
156
+ return np.sum(self.lattice_state) / self.num_sites
157
+
158
+ def correlation_function(self, plot=False):
159
+ """
160
+ Calculate the correlation function of the lattice.
161
+
162
+ Parameters
163
+ ----------
164
+ plot : bool, optional
165
+ If True, plots the correlation function. Default is False.
166
+
167
+ Returns
168
+ -------
169
+ tuple
170
+ The correlation function and the distances.
171
+ """
172
+ counter = 0
173
+ correlation_function = np.zeros(self.num_sites**2)
174
+ r_sq = np.zeros(self.num_sites**2).astype(int)
175
+
176
+ for i in np.arange(self.lattice_size):
177
+ for j in np.arange(self.lattice_size):
178
+ for k in np.arange(i, self.lattice_size):
179
+ check_var = 0
180
+ if i == k:
181
+ check_var = j
182
+ for l in np.arange(check_var, self.lattice_size):
183
+ x_distance = abs(j - l)
184
+ y_distance = abs(i - k)
185
+
186
+ if x_distance > self.lattice_size / 2:
187
+ x_distance = abs(self.lattice_size - x_distance)
188
+ if y_distance > self.lattice_size / 2:
189
+ y_distance = abs(self.lattice_size - y_distance)
190
+
191
+ distance = x_distance**2 + y_distance**2
192
+
193
+ r_sq[counter] = distance
194
+ correlation_function[counter] = self.lattice_state[i, j] * self.lattice_state[k, l]
195
+
196
+ counter += 1
197
+
198
+ corr = correlation_function[:counter]
199
+ dist = r_sq[:counter]
200
+
201
+ sort_ind = np.argsort(dist)
202
+ sorted_d = np.sort(dist)
203
+ sorted_c = corr[sort_ind]
204
+
205
+ unique_d, unique_indices_d = np.unique(sorted_d, return_index=True)
206
+ averaged_c = np.zeros(unique_d.size)
207
+
208
+ for i in np.arange(averaged_c.size - 1):
209
+ denom = unique_indices_d[i + 1] - unique_indices_d[i]
210
+ averaged_c[i] = np.sum(sorted_c[unique_indices_d[i]:unique_indices_d[i + 1]]) / denom
211
+
212
+ denom = unique_indices_d[-1] - unique_indices_d[-2]
213
+ averaged_c[-1] = np.sum(sorted_c[unique_indices_d[-2]:unique_indices_d[-1]]) / denom
214
+
215
+ if plot:
216
+ plt.plot(np.sqrt(unique_d), averaged_c)
217
+ plt.xlabel("Distance")
218
+ plt.ylabel("Correlation Function")
219
+ plt.title("Correlation Function vs Distance")
220
+ plt.show()
221
+
222
+ return averaged_c - self.magnetization()**2, np.sqrt(unique_d)
@@ -0,0 +1,319 @@
1
+ import numpy as np
2
+ import matplotlib.pyplot as plt
3
+ import random
4
+ import pickle as pkl
5
+ import imageio
6
+ import time
7
+ import os
8
+ from .isinglattice import IsingLattice
9
+
10
+ INF_TEMP = 100
11
+
12
+ def get_index(data):
13
+ """
14
+ Get the index where data falls below a threshold.
15
+
16
+ Parameters
17
+ ----------
18
+ data : np.ndarray
19
+ The array of data.
20
+
21
+ Returns
22
+ -------
23
+ int
24
+ The index where data falls below 10^-8.
25
+ """
26
+ for i in range(data.size):
27
+ if data[i] < 10**(-8):
28
+ return i
29
+ return data.size
30
+
31
+ def data2cut(data, index):
32
+ """
33
+ Cut data up to a given index.
34
+
35
+ Parameters
36
+ ----------
37
+ data : np.ndarray
38
+ The array of data.
39
+ index : int
40
+ The index to cut data.
41
+
42
+ Returns
43
+ -------
44
+ np.ndarray
45
+ The cut data.
46
+ """
47
+ return data[:index]
48
+
49
+ def distance2cut(distance, index):
50
+ """
51
+ Cut distances up to a given index.
52
+
53
+ Parameters
54
+ ----------
55
+ distance : np.ndarray
56
+ The array of distances.
57
+ index : int
58
+ The index to cut distances.
59
+
60
+ Returns
61
+ -------
62
+ np.ndarray
63
+ The cut distances.
64
+ """
65
+ return distance[:index]
66
+
67
+ def get_cor_len(cor_func, dist, index):
68
+ """
69
+ Calculate the correlation length.
70
+
71
+ Parameters
72
+ ----------
73
+ cor_func : np.ndarray
74
+ The correlation function values.
75
+ dist : np.ndarray
76
+ The distances.
77
+ index : int
78
+ The index up to which the data is considered.
79
+
80
+ Returns
81
+ -------
82
+ float
83
+ The correlation length.
84
+ """
85
+ cor_func_cut = data2cut(cor_func, index)
86
+ distance_cut = distance2cut(dist, index)
87
+
88
+ correlation_negative_check = np.sum(cor_func_cut * (distance_cut ** 2))
89
+ correlation_zero_check = np.sum(6 * cor_func_cut)
90
+
91
+ if correlation_zero_check == 0:
92
+ return 0
93
+ elif correlation_negative_check / correlation_zero_check < 0:
94
+ return 0
95
+ else:
96
+ return np.sqrt(correlation_negative_check / correlation_zero_check)
97
+
98
+ def scan_lattice(ising_lattice, temperature):
99
+ """
100
+ Perform a single Metropolis scan of the lattice.
101
+
102
+ Parameters
103
+ ----------
104
+ ising_lattice : IsingLattice
105
+ The Ising lattice.
106
+ temperature : float
107
+ The temperature of the system.
108
+ """
109
+ for _ in range(ising_lattice.num_sites):
110
+ i = random.randint(0, ising_lattice.lattice_size - 1)
111
+ j = random.randint(0, ising_lattice.lattice_size - 1)
112
+
113
+ energy_initial = ising_lattice.spin_energy(i, j)
114
+ ising_lattice.flip_spin(i, j)
115
+ energy_final = ising_lattice.spin_energy(i, j)
116
+ energy_change = energy_final - energy_initial
117
+ ising_lattice.flip_spin(i, j)
118
+
119
+ if temperature != 0:
120
+ if energy_change <= 0 or random.uniform(0, 1) <= np.exp(-energy_change / temperature):
121
+ ising_lattice.flip_spin(i, j)
122
+
123
+ def calculate_corr_size(lattice_size):
124
+ """
125
+ Calculate CORR_SIZE dynamically based on lattice size.
126
+
127
+ Parameters
128
+ ----------
129
+ lattice_size : int
130
+ The size of the lattice.
131
+
132
+ Returns
133
+ -------
134
+ int
135
+ The calculated CORR_SIZE.
136
+ """
137
+ unique_distances = set()
138
+
139
+ for i in range(lattice_size):
140
+ for j in range(lattice_size):
141
+ for k in range(lattice_size):
142
+ for l in range(lattice_size):
143
+ x_distance = min(abs(i - k), lattice_size - abs(i - k))
144
+ y_distance = min(abs(j - l), lattice_size - abs(j - l))
145
+ distance_squared = x_distance**2 + y_distance**2
146
+ unique_distances.add(distance_squared)
147
+
148
+ return len(unique_distances)
149
+
150
+ def monte_carlo_simulation(ising_lattice, temperature, num_scans, frequency_sweeps_to_collect_magnetization, plot_result=False, print_info=False, calculate_correlation=False):
151
+ """
152
+ Perform Monte Carlo simulation on the Ising lattice.
153
+
154
+ Parameters
155
+ ----------
156
+ ising_lattice : IsingLattice
157
+ The Ising lattice.
158
+ temperature : float
159
+ The temperature of the system.
160
+ num_scans : int
161
+ The number of scans to perform.
162
+ frequency_sweeps_to_collect_magnetization : int
163
+ The frequency of sweeps to collect magnetization.
164
+ plot_result : bool, optional
165
+ Whether to plot the result. Default is False.
166
+ print_info : bool, optional
167
+ Whether to print information. Default is False.
168
+ calculate_correlation : bool, optional
169
+ Whether to calculate correlation function and length. Default is False.
170
+
171
+ Returns
172
+ -------
173
+ tuple
174
+ Lattice configurations, energy records, magnetization records, correlation function records, correlation length records, distances.
175
+ """
176
+ start_time = time.time()
177
+
178
+ if print_info:
179
+ ising_lattice.print_info()
180
+
181
+ total_num_records = int(num_scans / frequency_sweeps_to_collect_magnetization) + 1
182
+ energy_records = np.zeros(total_num_records)
183
+ magnetization_records = np.zeros(total_num_records)
184
+
185
+ corr_size = calculate_corr_size(ising_lattice.lattice_size) if calculate_correlation else 0
186
+ correlation_function_records = np.zeros((total_num_records, corr_size)) if calculate_correlation else None
187
+ correlation_length_records = np.zeros(total_num_records) if calculate_correlation else None
188
+
189
+ increment_records = 0
190
+
191
+ lattice_configs = np.zeros((total_num_records, ising_lattice.lattice_size, ising_lattice.lattice_size))
192
+
193
+ for k in range(num_scans + frequency_sweeps_to_collect_magnetization):
194
+ scan_lattice(ising_lattice, temperature)
195
+ if k % frequency_sweeps_to_collect_magnetization == 0:
196
+ energy_records[increment_records] = ising_lattice.energy()
197
+ magnetization_records[increment_records] = ising_lattice.magnetization()
198
+ lattice_configs[increment_records] = ising_lattice.lattice_state
199
+
200
+ if calculate_correlation:
201
+ correlations, distances = ising_lattice.correlation_function(False)
202
+ correlation_function_records[increment_records] = correlations[:corr_size]
203
+
204
+ index = get_index(correlations)
205
+ correlation_length_records[increment_records] = get_cor_len(correlations, distances, index)
206
+
207
+ increment_records += 1
208
+ print(f"{increment_records} / {total_num_records} samples saved.")
209
+
210
+ print(f"For temperature= {temperature}, MC simulation executed in: {round(time.time() - start_time, 2)} seconds")
211
+
212
+ if plot_result:
213
+ ising_lattice.plot_lattice()
214
+
215
+ return (
216
+ lattice_configs,
217
+ energy_records,
218
+ magnetization_records,
219
+ correlation_function_records if calculate_correlation else None,
220
+ correlation_length_records if calculate_correlation else None,
221
+ distances if calculate_correlation else None
222
+ )
223
+
224
+ def dir_name(lattice_size, J1, J2, h, temperature):
225
+ return f'SQ_L_{lattice_size}_J1_{J1:.3f}_J2_{J2:.3f}_h_{h:.3f}_T_{temperature:.3f}'
226
+
227
+ def file_name(lattice_size, J1, J2, h, temperature, seed):
228
+ return f'SQ_L_{lattice_size}_J1_{J1:.3f}_J2_{J2:.3f}_h_{h:.3f}_T_{temperature:.3f}_s_{seed}'
229
+
230
+ def write_to_sub_directory(quantity, dir_name, file_name):
231
+ if not os.path.exists(dir_name):
232
+ os.mkdir(dir_name)
233
+ with open(os.path.join(dir_name, file_name), "wb") as file:
234
+ pkl.dump(quantity, file)
235
+
236
+ def write_txt_files(quantity, dir_name, file_name):
237
+ if not os.path.exists(dir_name):
238
+ os.mkdir(dir_name)
239
+ np.savetxt(os.path.join(dir_name, file_name), quantity, fmt='%1.3f')
240
+
241
+ def save_image_to_sub_directory(data, directory_name, file_name):
242
+ if not os.path.exists(directory_name):
243
+ os.mkdir(directory_name)
244
+ imageio.imwrite(os.path.join(directory_name, f"{file_name}.png"), data)
245
+
246
+ def thermalize(ising_lattice, num_scans, from_T, to_T):
247
+ """
248
+ Thermalize the lattice from a given temperature to a target temperature.
249
+
250
+ Parameters
251
+ ----------
252
+ ising_lattice : IsingLattice
253
+ The Ising lattice.
254
+ num_scans : int
255
+ The number of scans for thermalization.
256
+ from_T : float
257
+ The initial temperature.
258
+ to_T : float
259
+ The target temperature.
260
+ """
261
+ print(f"Equilibrating to T = {to_T:.2f} starting from T = {from_T:.2f}")
262
+ for k in np.linspace(from_T, to_T, num=num_scans):
263
+ scan_lattice(ising_lattice, k)
264
+ print(f"Reached T={to_T:.2f}. Beginning to collect data.")
265
+
266
+ def collect_monte_carlo_data(seed, lattice_size, J1, J2, h, num_scans, temperature, thermalization_scans, frequency_sweeps_to_collect_magnetization, calculate_correlation=False):
267
+ random.seed(seed)
268
+ print(f"Lattice size: {lattice_size} x {lattice_size}, J1= {J1}, J2= {J2}, h= {h}, SEED= {seed}\n")
269
+ temperature = np.append(INF_TEMP, temperature)
270
+
271
+ if 0 in temperature:
272
+ raise ValueError("Monte-Carlo does not work properly at T=0.")
273
+ if np.any(temperature < 0):
274
+ raise ValueError("Temperature cannot be a negative value.")
275
+
276
+ ising_lattice = IsingLattice(lattice_size, J1, J2, h)
277
+ num_temps = temperature.size
278
+
279
+ for i in range(num_temps - 1):
280
+ file_name_lattice = file_name(lattice_size, J1, J2, h, temperature[i+1], seed)
281
+ dir_name_data = dir_name(lattice_size, J1, J2, h, temperature[i+1])
282
+
283
+ total_num_configurations = int(num_scans / frequency_sweeps_to_collect_magnetization) + 1
284
+ file_exists = [os.path.isfile(os.path.join(dir_name_data, f"{file_name_lattice}_n_{configs * frequency_sweeps_to_collect_magnetization}.pkl")) for configs in range(total_num_configurations)]
285
+
286
+ if os.path.exists(dir_name_data) and not np.all(file_exists):
287
+ print(f"{np.argwhere(np.array(file_exists) == False)[0][0]} Previous configurations for SEED = {seed} with L = {lattice_size} T = {temperature[i+1]:.2f} J1 = {J1} J2 = {J2} h = {h}\n")
288
+
289
+ if np.all(file_exists):
290
+ print(f"ALL requested configurations for SEED = {seed} with L = {lattice_size} T = {temperature[i+1]:.2f} J1 = {J1} J2 = {J2} h = {h} already exist!\n")
291
+ continue
292
+
293
+ thermalize(ising_lattice, thermalization_scans, temperature[i], temperature[i+1])
294
+ print(f"START - MC simulation {i+1} / {num_temps-1}, T = {temperature[i+1]:.2f}")
295
+
296
+ lattice_configs, energy_records, magnetization_records, correlation_function_records, correlation_length_records, distances = monte_carlo_simulation(
297
+ ising_lattice, temperature[i+1], num_scans, frequency_sweeps_to_collect_magnetization, calculate_correlation=calculate_correlation)
298
+
299
+ for img in range(total_num_configurations):
300
+ file_name_img = f"{file_name_lattice}_n_{img * frequency_sweeps_to_collect_magnetization}"
301
+ data_sample = {
302
+ 'configuration': lattice_configs[img],
303
+ 'energy': energy_records[img],
304
+ 'magnetization': magnetization_records[img],
305
+ 'correlation_length': correlation_length_records[img] if calculate_correlation else None,
306
+ 'correlation_function': correlation_function_records[img] if calculate_correlation else None,
307
+ 'distances': distances if calculate_correlation else None
308
+ }
309
+
310
+ txt_data = np.array([data_sample['energy'], data_sample['magnetization'], data_sample['correlation_length']])
311
+ correlation_function_txt_data = np.array(data_sample['correlation_function']) if calculate_correlation else None
312
+ write_to_sub_directory(data_sample, dir_name_data, f"{file_name_img}.pkl")
313
+ save_image_to_sub_directory(lattice_configs[img].astype(np.uint8), dir_name_data, file_name_img)
314
+ write_txt_files(txt_data, dir_name_data, f"{file_name_img}.txt")
315
+ if calculate_correlation:
316
+ write_txt_files(correlation_function_txt_data, dir_name_data, f"{file_name_img}_correlation_function.txt")
317
+ write_txt_files(distances, dir_name_data, f"{file_name_img}_distances.txt")
318
+
319
+ print(f"END --- MC simulation {i+1} / {num_temps-1}, T = {temperature[i+1]:.2f}\n")
@@ -0,0 +1,35 @@
1
+ Metadata-Version: 2.1
2
+ Name: mcising
3
+ Version: 0.1
4
+ Summary: A package for generating Ising model data using Metropolis algorithm on a square lattice for nearest neighbor and next nearest neighbor interactions.
5
+ Home-page: https://github.com/bcivitcioglu/mcising
6
+ Author: Burak Ç.
7
+ Author-email: bcivitcioglu@gmail.com
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Classifier: Operating System :: OS Independent
11
+ Description-Content-Type: text/markdown
12
+
13
+ # mcising
14
+
15
+ mcising is a Python package for generating Ising model data using Monte Carlo simulations.
16
+
17
+ ## Installation
18
+
19
+ You can install the package using pip:
20
+
21
+ `pip install mcising`
22
+
23
+ ## Usage
24
+
25
+ You can generate Ising model data from the command line:
26
+
27
+ `generate_ising_data <seed> <lattice_size> <num_configs> <j1> <j2> [--T_init <T_init>] [--T_final <T_final>] [--T_step <T_step>] [--sweep_steps <sweep_steps>] [--thermalization_scans <thermalization_scans>] [--calculate_correlation]`
28
+
29
+ An example usage:
30
+
31
+ `generate_ising_data 42 10 100 1.0 0.5 --T_init 4.0 --T_final 0.1 --T_step 0.05 --sweep_steps 10 --thermalization_scans 5 --calculate_correlation`
32
+
33
+ ## Licence
34
+
35
+ This project is licensed under the MIT License.
@@ -0,0 +1,15 @@
1
+ README.md
2
+ setup.py
3
+ mcising/__init__.py
4
+ mcising/ising_data_generate.py
5
+ mcising/isinglattice.py
6
+ mcising/montecarlo.py
7
+ mcising.egg-info/PKG-INFO
8
+ mcising.egg-info/SOURCES.txt
9
+ mcising.egg-info/dependency_links.txt
10
+ mcising.egg-info/entry_points.txt
11
+ mcising.egg-info/requires.txt
12
+ mcising.egg-info/top_level.txt
13
+ tests/__init__.py
14
+ tests/test_isinglattice.py
15
+ tests/test_montecarlo.py
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ generate_ising_data = mcising.ising_data_generate:main
@@ -0,0 +1,3 @@
1
+ numpy
2
+ matplotlib
3
+ imageio
@@ -0,0 +1,2 @@
1
+ mcising
2
+ tests
mcising-0.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
mcising-0.1/setup.py ADDED
@@ -0,0 +1,33 @@
1
+ # setup.py
2
+ from setuptools import setup, find_packages
3
+
4
+ setup(
5
+ name="mcising",
6
+ version="0.1",
7
+ packages=find_packages(),
8
+ install_requires=[
9
+ "numpy",
10
+ "matplotlib",
11
+ "imageio"
12
+ ],
13
+ tests_require=[
14
+ "unittest",
15
+ "pytest"
16
+ ],
17
+ entry_points={
18
+ 'console_scripts': [
19
+ 'generate_ising_data=mcising.ising_data_generate:main',
20
+ ],
21
+ },
22
+ author="Burak Ç.",
23
+ author_email="bcivitcioglu@gmail.com",
24
+ description="A package for generating Ising model data using Metropolis algorithm on a square lattice for nearest neighbor and next nearest neighbor interactions.",
25
+ long_description=open('README.md').read(),
26
+ long_description_content_type='text/markdown',
27
+ url="https://github.com/bcivitcioglu/mcising",
28
+ classifiers=[
29
+ "Programming Language :: Python :: 3",
30
+ "License :: OSI Approved :: MIT License",
31
+ "Operating System :: OS Independent",
32
+ ],
33
+ )
@@ -0,0 +1 @@
1
+ # tests/__init__.py
@@ -0,0 +1,21 @@
1
+ import unittest
2
+ from mcising.isinglattice import IsingLattice
3
+
4
+ class TestIsingLattice(unittest.TestCase):
5
+
6
+ def test_initialization(self):
7
+ lattice = IsingLattice(lattice_size=10, J1=1.0, J2=0.5, h=0.0)
8
+ self.assertEqual(lattice.lattice_size, 10)
9
+ self.assertEqual(lattice.J1, 1.0)
10
+ self.assertEqual(lattice.J2, 0.5)
11
+ self.assertEqual(lattice.h, 0.0)
12
+ self.assertEqual(lattice.lattice_state.shape, (10, 10))
13
+
14
+ def test_flip_spin(self):
15
+ lattice = IsingLattice(lattice_size=10, J1=1.0, J2=0.5, h=0.0)
16
+ initial_spin = lattice.lattice_state[0, 0]
17
+ lattice.flip_spin(0, 0)
18
+ self.assertEqual(lattice.lattice_state[0, 0], -initial_spin)
19
+
20
+ if __name__ == '__main__':
21
+ unittest.main()
@@ -0,0 +1,49 @@
1
+ import unittest
2
+ from mcising.isinglattice import IsingLattice
3
+ from mcising.montecarlo import scan_lattice, monte_carlo_simulation
4
+
5
+ class TestMonteCarlo(unittest.TestCase):
6
+
7
+ def setUp(self):
8
+ self.lattice = IsingLattice(lattice_size=10, J1=1.0, J2=0.5, h=0.0)
9
+ self.temperature = 1.0
10
+ self.num_scans = 100
11
+ self.frequency_sweeps_to_collect_magnetization = 10
12
+
13
+ def test_scan_lattice(self):
14
+ initial_energy = self.lattice.energy()
15
+ scan_lattice(self.lattice, self.temperature)
16
+ self.assertNotEqual(self.lattice.energy(), initial_energy)
17
+
18
+ def test_monte_carlo_simulation_without_correlation(self):
19
+ configs, energies, magnetizations, corrs, corr_lengths, distances = monte_carlo_simulation(
20
+ self.lattice,
21
+ self.temperature,
22
+ self.num_scans,
23
+ self.frequency_sweeps_to_collect_magnetization,
24
+ calculate_correlation=False
25
+ )
26
+ self.assertIsNotNone(configs)
27
+ self.assertIsNotNone(energies)
28
+ self.assertIsNotNone(magnetizations)
29
+ self.assertIsNone(corrs)
30
+ self.assertIsNone(corr_lengths)
31
+ self.assertIsNone(distances)
32
+
33
+ def test_monte_carlo_simulation_with_correlation(self):
34
+ configs, energies, magnetizations, corrs, corr_lengths, distances = monte_carlo_simulation(
35
+ self.lattice,
36
+ self.temperature,
37
+ self.num_scans,
38
+ self.frequency_sweeps_to_collect_magnetization,
39
+ calculate_correlation=True
40
+ )
41
+ self.assertIsNotNone(configs)
42
+ self.assertIsNotNone(energies)
43
+ self.assertIsNotNone(magnetizations)
44
+ self.assertIsNotNone(corrs)
45
+ self.assertIsNotNone(corr_lengths)
46
+ self.assertIsNotNone(distances)
47
+
48
+ if __name__ == '__main__':
49
+ unittest.main()