Skip to content

Commit 91f983e

Browse files
author
shimwell
committed
made python driver for the source
1 parent 607319d commit 91f983e

4 files changed

Lines changed: 378 additions & 26 deletions

File tree

parametric_plasma_source/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ C_FLAGS = -fPIC
2626
CXX_FLAGS = -fPIC
2727

2828
#this directory will need changing if your openmc path is different
29-
OPENMC_DIR = /opt/openmc
29+
OPENMC_DIR = $openmc$
3030
OPENMC_INC_DIR = $(OPENMC_DIR)/include
3131
OPENMC_LIB_DIR = $(OPENMC_DIR)/lib
3232
# setting the so name is important

parametric_plasma_source/plasma.py

Lines changed: 353 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,353 @@
1+
"""
2+
This file is part of PARAMAK which is a design tool capable
3+
of creating 3D CAD models compatible with automated neutronics
4+
analysis.
5+
6+
PARAMAK is released under GNU General Public License v3.0.
7+
Go to https://github.com/Shimwell/paramak/blob/master/LICENSE
8+
for full license details.
9+
10+
This program is free software: you can redistribute it and/or modify
11+
it under the terms of the GNU General Public License as published by
12+
the Free Software Foundation, either version 3 of the License, or
13+
(at your option) any later version.
14+
15+
Copyright (C) 2019 UKAEA
16+
17+
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
18+
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
19+
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
20+
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
21+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22+
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
23+
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
24+
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
25+
"""
26+
import math
27+
import os
28+
from pathlib import Path
29+
import tempfile
30+
import shutil
31+
32+
import numpy as np
33+
import scipy
34+
35+
36+
class Plasma():
37+
38+
def __init__(self,
39+
elongation=2.,
40+
major_radius=450,
41+
minor_radius=150,
42+
single_null=True,
43+
triangularity=0.55,
44+
ion_density_pedistal=1.09e20,
45+
ion_density_seperatrix=3e19,
46+
ion_density_origin=1.09e20,
47+
ion_temperature_pedistal=6.09,
48+
ion_temperature_seperatrix=0.1,
49+
ion_temperature_origin=45.9,
50+
pedistal_radius=0.8,
51+
ion_density_peaking_factor=1,
52+
ion_temperature_peaking_factor=8.06,
53+
shafranov_shift=0.0,
54+
number_of_bins=100,
55+
plasma_type=1,
56+
openmc_install_directory = '/opt/openmc/'
57+
):
58+
59+
# properties needed for plasma shapes
60+
self.elongation = elongation
61+
self.major_radius = major_radius
62+
self.minor_radius = minor_radius
63+
self.single_null = single_null
64+
self.triangularity = triangularity
65+
self.ion_density_pedistal = ion_density_pedistal # ions per m^3
66+
self.ion_density_seperatrix = ion_density_seperatrix
67+
self.ion_density_origin = ion_density_origin
68+
self.ion_temperature_pedistal = ion_temperature_pedistal
69+
self.ion_temperature_seperatrix = ion_temperature_seperatrix
70+
self.ion_temperature_origin = ion_temperature_origin
71+
self.pedistal_radius = pedistal_radius # pedistal major rad
72+
self.ion_density_peaking_factor = ion_density_peaking_factor
73+
self.ion_temperature_peaking_factor = ion_temperature_peaking_factor
74+
self.shafranov_shift = shafranov_shift
75+
self.number_of_bins = number_of_bins
76+
self.plasma_type = plasma_type # 0 = L mode anything else H/A mode
77+
self.openmc_install_directory = openmc_install_directory
78+
79+
# parametric plasma source files read into memory
80+
self.plasma_make_file = Path(Path(__file__).parent/'Makefile').read_text()
81+
self.plasma_source_cpp_file = Path(Path(__file__).parent/'plasma_source.cpp').read_text()
82+
self.plasma_source_hpp_file = Path(Path(__file__).parent/'plasma_source.hpp').read_text()
83+
self.source_sampling_cpp_file = Path(Path(__file__).parent/'source_sampling.cpp').read_text()
84+
85+
@property
86+
def openmc_install_directory(self):
87+
return self._openmc_install_directory
88+
89+
@openmc_install_directory.setter
90+
def openmc_install_directory(self, value):
91+
if Path(value).exists() == False:
92+
raise ValueError('openmc_install_directory is out of range')
93+
else:
94+
self._openmc_install_directory = value
95+
96+
@property
97+
def plasma_type(self):
98+
return self._plasma_type
99+
100+
@plasma_type.setter
101+
def plasma_type(self, plasma_type):
102+
if plasma_type < 0:
103+
raise ValueError('plasma_type is out of range')
104+
else:
105+
self._plasma_type = plasma_type
106+
107+
@property
108+
def number_of_bins(self):
109+
return self._number_of_bins
110+
111+
@number_of_bins.setter
112+
def number_of_bins(self, number_of_bins):
113+
if number_of_bins < 0:
114+
raise ValueError('number_of_bins is out of range')
115+
else:
116+
self._number_of_bins = number_of_bins
117+
118+
@property
119+
def shafranov_shift(self):
120+
return self._shafranov_shift
121+
122+
@shafranov_shift.setter
123+
def shafranov_shift(self, shafranov_shift):
124+
if shafranov_shift < 0:
125+
raise ValueError('shafranov_shift is out of range')
126+
else:
127+
self._shafranov_shift = shafranov_shift
128+
129+
@property
130+
def ion_temperature_peaking_factor(self):
131+
return self._ion_temperature_peaking_factor
132+
133+
@ion_temperature_peaking_factor.setter
134+
def ion_temperature_peaking_factor(self, ion_temperature_peaking_factor):
135+
if ion_temperature_peaking_factor < 0:
136+
raise ValueError('ion_temperature_peaking_factor is out of range')
137+
else:
138+
self._ion_temperature_peaking_factor = ion_temperature_peaking_factor
139+
140+
@property
141+
def ion_density_peaking_factor(self):
142+
return self._ion_density_peaking_factor
143+
144+
@ion_density_peaking_factor.setter
145+
def ion_density_peaking_factor(self, ion_density_peaking_factor):
146+
if ion_density_peaking_factor < 0:
147+
raise ValueError('ion_density_peaking_factor is out of range')
148+
else:
149+
self._ion_density_peaking_factor = ion_density_peaking_factor
150+
151+
@property
152+
def pedistal_radius(self):
153+
return self._pedistal_radius
154+
155+
@pedistal_radius.setter
156+
def pedistal_radius(self, pedistal_radius):
157+
if pedistal_radius < 0:
158+
raise ValueError('pedistal_radius is out of range')
159+
else:
160+
self._pedistal_radius = pedistal_radius
161+
162+
@property
163+
def ion_temperature_origin(self):
164+
return self._ion_temperature_origin
165+
166+
@ion_temperature_origin.setter
167+
def ion_temperature_origin(self, ion_temperature_origin):
168+
if ion_temperature_origin < 0:
169+
raise ValueError('ion_temperature_origin is out of range')
170+
else:
171+
self._ion_temperature_origin = ion_temperature_origin
172+
173+
@property
174+
def ion_temperature_seperatrix(self):
175+
return self._ion_temperature_seperatrix
176+
177+
@ion_temperature_seperatrix.setter
178+
def ion_temperature_seperatrix(self, ion_temperature_seperatrix):
179+
if ion_temperature_seperatrix < 0:
180+
raise ValueError('ion_temperature_seperatrix is out of range')
181+
else:
182+
self._ion_temperature_seperatrix = ion_temperature_seperatrix
183+
184+
@property
185+
def ion_temperature_pedistal(self):
186+
return self._ion_temperature_pedistal
187+
188+
@ion_temperature_pedistal.setter
189+
def ion_temperature_pedistal(self, ion_temperature_pedistal):
190+
if ion_temperature_pedistal < 0:
191+
raise ValueError('ion_temperature_pedistal is out of range')
192+
else:
193+
self._ion_temperature_pedistal = ion_temperature_pedistal
194+
195+
@property
196+
def ion_density_origin(self):
197+
return self._ion_density_origin
198+
199+
@ion_density_origin.setter
200+
def ion_density_origin(self, ion_density_origin):
201+
if ion_density_origin < 0:
202+
raise ValueError('ion_density_origin is out of range')
203+
else:
204+
self._ion_density_origin = ion_density_origin
205+
206+
@property
207+
def ion_density_seperatrix(self):
208+
return self._ion_density_seperatrix
209+
210+
@ion_density_seperatrix.setter
211+
def ion_density_seperatrix(self, ion_density_seperatrix):
212+
if ion_density_seperatrix < 0:
213+
raise ValueError('ion_density_seperatrix is out of range')
214+
else:
215+
self._ion_density_seperatrix = ion_density_seperatrix
216+
217+
@property
218+
def triangularity(self):
219+
return self._triangularity
220+
221+
@triangularity.setter
222+
def triangularity(self, triangularity):
223+
if triangularity > 2000 or triangularity < -2000:
224+
raise ValueError('triangularity is out of range')
225+
else:
226+
self._triangularity = triangularity
227+
228+
@property
229+
def single_null(self):
230+
return self._single_null
231+
232+
@single_null.setter
233+
def single_null(self, single_null):
234+
if type(single_null) != bool :
235+
raise ValueError('single_null must be True or False')
236+
else:
237+
self._single_null = single_null
238+
239+
@property
240+
def minor_radius(self):
241+
return self._minor_radius
242+
243+
@minor_radius.setter
244+
def minor_radius(self, minor_radius):
245+
if minor_radius > 2000 or minor_radius < 1:
246+
raise ValueError('minor_radius is out of range')
247+
else:
248+
self._minor_radius = minor_radius
249+
250+
@property
251+
def major_radius(self):
252+
return self._major_radius
253+
254+
@major_radius.setter
255+
def major_radius(self, major_radius):
256+
if major_radius > 2000 or major_radius < 1:
257+
raise ValueError('major_radius is out of range')
258+
else:
259+
self._major_radius = major_radius
260+
261+
@property
262+
def elongation(self):
263+
return self._elongation
264+
265+
@elongation.setter
266+
def elongation(self, elongation):
267+
if elongation > 4 or elongation < 0:
268+
raise ValueError('elongation is out of range')
269+
else:
270+
self._elongation = elongation
271+
272+
@property
273+
def ion_density_pedistal(self):
274+
return self._ion_density_pedistal
275+
276+
@ion_density_pedistal.setter
277+
def ion_density_pedistal(self, ion_density_pedistal):
278+
if ion_density_pedistal > 10e22 or ion_density_pedistal < 1e4:
279+
raise ValueError('ion_density_pedistal is out of range')
280+
else:
281+
self._ion_density_pedistal = ion_density_pedistal
282+
283+
284+
def export_plasma_source(self, output_filename):
285+
"""Writes and compiles custom plasma source for the reactor
286+
:param output_folder: the output folder where the .so complied plasma source will be created
287+
:type output_folder: str
288+
...
289+
:return: filename of the compiled source
290+
:rtype: str
291+
"""
292+
293+
if self.openmc_install_directory is None:
294+
raise ValueError('directory must be set to create .so file')
295+
296+
temp_folder = Path(tempfile.mkdtemp())
297+
print(temp_folder)
298+
Path(output_filename).parent.mkdir(parents=True, exist_ok=True)
299+
300+
editted_plasma_make_file = self.plasma_make_file.replace('$openmc$', self.openmc_install_directory)
301+
with open(temp_folder/'Makefile', "w") as text_file:
302+
text_file.write(editted_plasma_make_file)
303+
304+
with open(temp_folder/'plasma_source.cpp', "w") as text_file:
305+
text_file.write(self.plasma_source_cpp_file)
306+
307+
with open(temp_folder/'plasma_source.hpp', "w") as text_file:
308+
text_file.write(self.plasma_source_hpp_file)
309+
310+
plasma_varibles = [
311+
('$ion_density_pedistal$',str(self.ion_density_pedistal)),
312+
('$ion_density_seperatrix$',str(self.ion_density_seperatrix)),
313+
('$ion_density_origin$',str(self.ion_density_origin)),
314+
('$ion_temperature_pedistal$',str(self.ion_temperature_pedistal)),
315+
('$ion_temperature_seperatrix$',str(self.ion_temperature_seperatrix)),
316+
('$ion_temperature_origin$',str(self.ion_temperature_origin)),
317+
('$pedistal_radius$',str(self.pedistal_radius)),
318+
('$ion_density_peaking_factor$',str(self.ion_density_peaking_factor)),
319+
('$ion_temperature_peaking_factor$',str(self.ion_temperature_peaking_factor)),
320+
('$minor_radius$',str(self.minor_radius / 100.)),
321+
('$major_radius$',str(self.major_radius / 100.)),
322+
('$elongation$',str(self.elongation)),
323+
('$triangularity$',str(self.triangularity)),
324+
('$shafranov_shift$',str(self.shafranov_shift / 100.)),
325+
('$number_of_bins$',str(self.number_of_bins)),
326+
('$plasma_type$',str(self.plasma_type))
327+
]
328+
329+
editted_source_sampling_cpp_file = self.source_sampling_cpp_file
330+
for entry in plasma_varibles:
331+
if entry[0] in self.source_sampling_cpp_file:
332+
editted_source_sampling_cpp_file = editted_source_sampling_cpp_file.replace(entry[0], entry[1])
333+
else:
334+
raise ValueError(entry[0],' string not found in ', self.source_sampling_cpp_file)
335+
336+
337+
with open(temp_folder/'source_sampling.cpp', "w") as text_file:
338+
text_file.write(editted_source_sampling_cpp_file)
339+
340+
cwd = os.getcwd()
341+
os.chdir(Path(temp_folder))
342+
343+
os.system('make clean')
344+
os.system('make')
345+
346+
347+
348+
os.chdir(cwd)
349+
shutil.move(temp_folder/'source_sampling.so', output_filename)
350+
print('parametric plasma source compiled and saved to ', output_filename)
351+
shutil.rmtree(temp_folder)
352+
353+
return output_filename

parametric_plasma_source/plasma_source.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -159,8 +159,7 @@ void PlasmaSource::setup_plasma_source()
159159
{
160160
double ion_d; // ion density
161161
double ion_t; // ion temp
162-
double sig_dt; // dt xs
163-
162+
164163
std::vector<double> src_strength; // the source strength, n/m3
165164
double r;
166165

0 commit comments

Comments
 (0)