11# simple monoblock simulation in festim 
2- 
32import  festim  as  F 
43import  numpy  as  np 
54import  h_transport_materials  as  htm 
6- 
5+ import  ufl 
6+ from  dolfinx .fem .function  import  Constant 
7+ from  scipy  import  constants 
8+ import  dolfinx .fem  as  fem 
9+ import  dolfinx 
10+ 
11+ # dolfinx.log.set_log_level(dolfinx.log.LogLevel.INFO) 
12+ 
13+ ############# CUSTOM CLASSES FOR PULSED FLUXES & RECOMBO BC ############# 
14+ 
15+ class  PulsedSource (F .ParticleSource ):
16+     def  __init__ (self , flux , distribution , volume , species ):
17+         self .flux  =  flux 
18+         self .distribution  =  distribution 
19+         super ().__init__ (None , volume , species )
20+ 
21+     @property  
22+     def  time_dependent (self ):
23+         return  True 
24+ 
25+     def  create_value_fenics (self , mesh , temperature , t : Constant ):
26+         self .flux_fenics  =  Constant (mesh , float (self .flux (t )))
27+         x  =  ufl .SpatialCoordinate (mesh )
28+         self .distribution_fenics  =  self .distribution (x )
29+ 
30+         self .value_fenics  =  self .flux_fenics  *  self .distribution_fenics 
31+ 
32+     def  update (self , t : float ):
33+         self .flux_fenics .value  =  self .flux (t )
34+ 
35+ class  FluxFromSurfaceReaction (F .SurfaceFlux ):
36+     def  __init__ (self , reaction : F .SurfaceReactionBC ):
37+         super ().__init__ (
38+             F .Species (),  # just a dummy species here 
39+             reaction .subdomain ,
40+         )
41+         self .reaction  =  reaction .flux_bcs [0 ]
42+ 
43+     def  compute (self , ds ):
44+         self .value  =  fem .assemble_scalar (
45+             fem .form (self .reaction .value_fenics  *  ds (self .surface .id ))
46+         )
47+         self .data .append (self .value )
48+ 
49+ # TODO: ADJUST TO HANDLE ANY STRAIGHT W 6MM SIMU 
50+ mb  =  50 
51+ 
52+ ############# Input Flux, Heat Data ############# 
53+ with  open ('scenario.txt' , 'r' ) as  file :
54+     lines  =  []
55+     for  line  in  file :
56+         lines .append (line .split ())
57+ lines  =  lines [1 :]
58+ 
59+ DINA_data  =  np .loadtxt ('Binned_Flux_Data.dat' , skiprows = 1 )
60+ ion_flux  =  DINA_data [:,2 ][mb - 1 ]
61+ atom_flux  =  DINA_data [:,3 ][mb - 1 ]
62+ heat  =  DINA_data [:,- 2 ][mb - 1 ]
763
864my_model  =  F .HydrogenTransportProblem ()
965
10- # building 1D mesh, W mb  
66+ ############# Material Parameters #############  
1167
12- L  =  6e-3    # m 
13- vertices  =  np .concatenate (
68+ L  =  6e-3  # m 
69+ vertices  =  np .concatenate (  # 1D mesh with extra refinement 
1470    [
1571        np .linspace (0 , 30e-9 , num = 200 ),
1672        np .linspace (30e-9 , 3e-6 , num = 300 ),
2076)
2177my_model .mesh  =  F .Mesh1D (vertices )
2278
23- 
24- # W material parameters  
79+ # W material parameters  
80+ # TODO integrate with htm   
2581w_density  =  6.3382e28   # atoms/m3 
26- tungsten_diff  =  htm .diffusivities .filter (material = htm .TUNGSTEN ).mean ()
82+ #  tungsten_diff = htm.diffusivities.filter(material=htm.TUNGSTEN).mean()
2783tungsten  =  F .Material (
28-     D_0 = tungsten_diff . pre_exp . magnitude , 
29-     E_D = tungsten_diff . act_energy . magnitude ,
84+     D_0 = 4.1e-7 ,  # Hodille 2015 paper pg 426 
85+     E_D = 0.39 ,
3086    name = "tungsten" ,
3187)
3288
33- # subdomains 
89+ # mb  subdomains 
3490w_subdomain  =  F .VolumeSubdomain1D (id = 1 , borders = [0 , L ], material = tungsten )
3591inlet  =  F .SurfaceSubdomain1D (id = 1 , x = 0 )
3692outlet  =  F .SurfaceSubdomain1D (id = 2 , x = L )
52108trap3_D  =  F .Species ("trap3_D" , mobile = False )
53109trap3_T  =  F .Species ("trap3_T" , mobile = False )
54110
55- 
56111# traps 
57112empty_trap1  =  F .ImplicitSpecies (  # implicit trap 1 
58113    n = 6.338e24 ,  # 1e-4 at.fr. 
66121    name = "empty_trap2" ,
67122)
68123
124+ # density_func =  
69125empty_trap3  =  F .ImplicitSpecies (  # fermi-dirac-like trap 3 
70-     n = 6.338e27 ,  # 1e-1 at.fr. 
126+     n = 6.338e27 , # density_func  # 1e-1 at.fr.
71127    others = [trap3_T , trap3_D ],
72128    name = "empty_trap3" ,
73129)
141197    ),
142198]
143199
144- # temperature 
145- # my_model.temperature = 1000 - (1000-350)/L*x 
146- my_model .temperature  =  1000 
200+ ############# Pulse Parameters (s) ############# 
201+ pulses_per_day  =  13 
202+ 
203+ flat_top_duration  =  50 * pulses_per_day 
204+ ramp_up_duration  =  33 * pulses_per_day  
205+ ramp_down_duration  =  35 * pulses_per_day 
206+ dwelling_time  =  72000  # 20 hours 
207+ 
208+ total_time_pulse  =  flat_top_duration  +  ramp_up_duration  +  ramp_down_duration 
209+ total_time_cycle  =  total_time_pulse  +  dwelling_time 
210+ 
211+ isotope_split  =  0.5 
212+ 
213+ ############# Temperature Parameters (K) ############# 
214+ T_coolant  =  343  # 70 degree C cooling water 
215+ 
216+ def  T_surface (t ): # plasma-facing side 
217+     return  1.1e-4 * heat + T_coolant 
218+ 
219+ def  T_rear (t ): # coolant facing side 
220+     return  2.2e-5 * heat + T_coolant 
221+ 
222+ def  T_function (x , t : Constant ):
223+     a  =  (T_rear (t ) -  T_surface (t )) /  L 
224+     b  =  T_surface (t )
225+     flat_top_value  =  a  *  x [0 ] +  b 
226+     resting_value  =  T_coolant 
227+     return  (
228+         flat_top_value 
229+         if  float (t ) %  total_time_cycle  <  total_time_pulse 
230+         else  resting_value 
231+     )
232+ 
233+ my_model .temperature  =  T_function 
234+ 
235+ ############# Flux Parameters ############# 
236+ 
237+ def  gaussian_distribution (x ):
238+     depth  =  3e-9 
239+     width  =  1e-9 
240+     return  ufl .exp (- ((x [0 ] -  depth ) **  2 ) /  (2  *  width ** 2 ))
241+ 
242+ def  deuterium_ion_flux (t : Constant ):
243+     flat_top_value  =  ion_flux * isotope_split  
244+     resting_value  =  0 
245+     return  (
246+         flat_top_value 
247+         if  float (t ) %  total_time_cycle  <  total_time_pulse 
248+         else  resting_value 
249+     )
250+ 
251+ def  tritium_ion_flux (t : Constant ):
252+     flat_top_value  =  ion_flux * isotope_split   
253+     resting_value  =  0 
254+     return  (
255+         flat_top_value 
256+         if  float (t ) %  total_time_cycle  <  total_time_pulse 
257+         else  resting_value 
258+     )
259+ 
260+ def  deuterium_atom_flux (t : Constant ):
261+     flat_top_value  =  atom_flux * isotope_split  
262+     resting_value  =  0 
263+     return  (
264+         flat_top_value 
265+         if  float (t ) %  total_time_cycle  <  total_time_pulse 
266+         else  resting_value 
267+     )
268+ 
269+ def  tritium_atom_flux (t : Constant ):
270+     flat_top_value  =  atom_flux * isotope_split   
271+     resting_value  =  0 
272+     return  (
273+         flat_top_value 
274+         if  float (t ) %  total_time_cycle  <  total_time_pulse 
275+         else  resting_value 
276+     )
277+ 
278+ 
279+ my_model .sources  =  [
280+     PulsedSource (
281+         flux = deuterium_ion_flux ,
282+         distribution = gaussian_distribution ,
283+         species = mobile_D ,
284+         volume = w_subdomain ,
285+     ),
286+     PulsedSource (
287+         flux = tritium_ion_flux ,
288+         distribution = gaussian_distribution ,
289+         species = mobile_T ,
290+         volume = w_subdomain 
291+     ),
292+     PulsedSource (
293+         flux = deuterium_atom_flux ,
294+         distribution = gaussian_distribution ,
295+         species = mobile_D ,
296+         volume = w_subdomain ,
297+     ),
298+     PulsedSource (
299+         flux = tritium_atom_flux ,
300+         distribution = gaussian_distribution ,
301+         species = mobile_T ,
302+         volume = w_subdomain 
303+     )
304+     
305+ ]
306+ 
307+ ############# Boundary Conditions ############# 
308+ surface_reaction_dd  =  F .SurfaceReactionBC (
309+     reactant = [mobile_D , mobile_D ],
310+     gas_pressure = 0 ,
311+     k_r0 = 7.94e-17 ,
312+     E_kr = - 2 ,
313+     k_d0 = 0 ,
314+     E_kd = 0 ,
315+     subdomain = inlet ,
316+ )
317+ 
318+ surface_reaction_tt  =  F .SurfaceReactionBC (
319+     reactant = [mobile_T , mobile_T ],
320+     gas_pressure = 0 ,
321+     k_r0 = 7.94e-17 ,
322+     E_kr = - 2 ,
323+     k_d0 = 0 ,
324+     E_kd = 0 ,
325+     subdomain = inlet ,
326+ )
147327
148- # boundary conditions 
328+ surface_reaction_dt  =  F .SurfaceReactionBC (
329+     reactant = [mobile_D , mobile_T ],
330+     gas_pressure = 0 ,
331+     k_r0 = 7.94e-17 ,
332+     E_kr = - 2 ,
333+     k_d0 = 0 ,
334+     E_kd = 0 ,
335+     subdomain = inlet ,
336+ )
149337
150338my_model .boundary_conditions  =  [
151-     F .DirichletBC (subdomain = inlet , value = 1e20 , species = mobile_T ),
152-     F .DirichletBC (subdomain = inlet , value = 1e19 , species = mobile_D ),
153-     F .DirichletBC (subdomain = outlet , value = 0 , species = mobile_T ),
154-     F .DirichletBC (subdomain = outlet , value = 0 , species = mobile_D ),
339+     surface_reaction_dd ,
340+     surface_reaction_dt , 
341+     surface_reaction_tt 
155342]
156343
157- # exports  
344+ ############# Exports #############  
158345
159- left_flux  =  F .SurfaceFlux (field = mobile_T , surface = inlet )
160- right_flux  =  F .SurfaceFlux (field = mobile_T , surface = outlet )
161- 
162- folder  =  "multi_isotope_trapping_example" 
346+ folder  =  f'mb{ mb }  
163347
164348my_model .exports  =  [
165349    F .VTXExport (f"{ folder }  , field = mobile_T ),
178362    my_model .exports .append (quantity )
179363    quantities [species .name ] =  quantity 
180364
181- # settings  
365+ ############# Settings #############  
182366
183367my_model .settings  =  F .Settings (
184-     atol = 1e-10  , rtol = 1e-10  , max_iterations = 30 , final_time = 3000 
368+     atol = 1e-15  , rtol = 1e-15  , max_iterations = 1000 , final_time = 3000 
185369)
186370
187371my_model .settings .stepsize  =  F .Stepsize (initial_value = 20 )
188372
189- # run simu  
373+ ############# Run Simu #############  
190374
191375my_model .initialise ()
192376my_model .run ()
193377
378+ ############# Results Plotting ############# 
194379
195380import  matplotlib .pyplot  as  plt 
196381
217402plt .xlabel ("Time (s)" )
218403plt .ylabel ("Total quantity (atoms/m2)" )
219404plt .legend ()
220- plt .show ()
405+ plt .show ()
0 commit comments