1
1
#!/usr/bin/env python3
2
2
# -*- coding: utf-8 -*-
3
3
"""
4
- A Graphical User Interface for create_rve.py and cuboid_grains .py
4
+ A Graphical User Interface for create_rve.py, cuboid_grains.py and cpnvert_ang2rve .py
5
5
Created on May 2024
6
+ last Upaate Sep 2024
6
7
@author: Ronak Shoghi, Alexander Hartmaier
7
8
"""
8
9
import time
16
17
from matplotlib .backends .backend_tkagg import FigureCanvasTkAgg
17
18
from kanapy .initializations import RVE_creator , mesh_creator
18
19
from kanapy .entities import Simulation_Box
20
+ from tkinter import filedialog
19
21
20
22
""" ===== Global Subroutines ===== """
21
23
@@ -343,7 +345,7 @@ def export_abq(self):
343
345
344
346
345
347
class cuboid_rve (object ):
346
- """ Functions for RVEs with cuboid grains
348
+ """ Functions for RVEs with cuboid grains
347
349
second tab"""
348
350
349
351
def __init__ (self ):
@@ -522,6 +524,195 @@ def export_abq(self):
522
524
self .create_cubes_and_plot ()
523
525
self .ms .write_abq ('v' )
524
526
527
+ class ebsd_rve (object ):
528
+ """Functions for creating RVE from EBSD data"""
529
+
530
+ def __init__ (self ):
531
+ # define standard parameters
532
+ self .ebsd = None
533
+ self .ms = None
534
+ self .ms_stats = None
535
+ self .stats_canvas = None
536
+ self .rve_canvas = None
537
+ self .texture_var = tk .StringVar (value = "unimodal" )
538
+ self .matname_var = tk .StringVar (value = "Simulanium" )
539
+ self .nvox_var = tk .IntVar (value = 40 )
540
+ self .size_var = tk .IntVar (value = 30 )
541
+ self .periodic_var = tk .BooleanVar (value = True )
542
+
543
+ if self .texture_var .get () == 'random' :
544
+ self .kernel_var = tk .StringVar (value = "-" )
545
+ self .euler_var = tk .StringVar (value = "-" )
546
+ else :
547
+ self .kernel_var = tk .StringVar (value = "7.5" )
548
+ self .euler_var = tk .StringVar (value = "0.0, 45.0, 0.0" )
549
+
550
+ self .texture_var .trace ('w' , self .update_kernel_var )
551
+ self .texture_var .trace ('w' , self .update_euler_var )
552
+
553
+ # plot frames
554
+ tab3 = ttk .Frame (notebook )
555
+ notebook .add (tab3 , text = "EBSD Import" )
556
+ main_frame = ttk .Frame (tab3 )
557
+ main_frame .grid (row = 0 , column = 0 , sticky = 'nsew' , padx = 20 , pady = 20 )
558
+
559
+ plot_frame = ttk .Frame (tab3 )
560
+ plot_frame .grid (row = 0 , column = 1 , sticky = 'nsew' , padx = 20 , pady = 20 )
561
+ plot_frame .rowconfigure (0 , weight = 1 )
562
+ plot_frame .columnconfigure (0 , weight = 1 )
563
+
564
+ self .stats_plot_frame = ttk .Frame (plot_frame )
565
+ self .stats_plot_frame .grid (row = 0 , column = 0 , sticky = 'nsew' )
566
+
567
+ self .rve_plot_frame = ttk .Frame (plot_frame )
568
+ self .rve_plot_frame .grid (row = 1 , column = 0 , sticky = 'nsew' )
569
+
570
+ # define labels and entries
571
+ line_seq = np .linspace (0 , 50 , dtype = int )
572
+ line = iter (line_seq )
573
+ ttk .Label (main_frame , text = "General Parameters" , font = ("Helvetica" , 12 , "bold" )) \
574
+ .grid (row = next (line ), column = 0 , columnspan = 2 , pady = (10 , 0 ), sticky = 'w' )
575
+ add_label_and_entry (main_frame , next (line ), "Material Name" , self .matname_var , bold = False )
576
+ add_label_and_entry (main_frame , next (line ), "Number of Voxels" , self .nvox_var , bold = False )
577
+ add_label_and_entry (main_frame , next (line ), "Size of RVE (in micron)" , self .size_var , bold = False )
578
+ add_label_and_entry (main_frame , next (line ), "Periodic" , self .periodic_var , entry_type = "checkbox" , bold = False )
579
+
580
+ # Orientation Parameters
581
+ ttk .Label (main_frame , text = "Orientation Parameters" , font = ("Helvetica" , 12 , "bold" )) \
582
+ .grid (row = next (line ), column = 0 , columnspan = 2 , pady = (10 , 0 ), sticky = 'w' )
583
+ add_label_and_entry (main_frame , next (line ), "Texture" , self .texture_var , entry_type = "combobox" ,
584
+ options = ["random" , "unimodal" ], bold = False )
585
+ add_label_and_entry (main_frame , next (line ), "Kernel Half Width (degree)" , self .kernel_var , bold = False )
586
+ add_label_and_entry (main_frame , next (line ), "Euler Angles (degree)" , self .euler_var , bold = False )
587
+
588
+ # create buttons
589
+ button_frame = ttk .Frame (main_frame )
590
+ button_frame .grid (row = next (line ), column = 0 , columnspan = 2 , pady = 10 , sticky = 'ew' )
591
+
592
+ button_upload_ebsd = ttk .Button (button_frame , text = "Upload EBSD File" , style = 'TButton' ,
593
+ command = self .upload_ebsd )
594
+ button_upload_ebsd .grid (row = 0 , column = 0 , padx = (10 , 5 ), pady = 5 , sticky = 'ew' )
595
+
596
+ button_show_ebsd = ttk .Button (button_frame , text = "Show EBSD" , style = 'TButton' )
597
+ button_show_ebsd .grid (row = 0 , column = 1 , padx = 5 , pady = 5 , sticky = 'ew' )
598
+
599
+ button_create_rve = ttk .Button (button_frame , text = "Create RVE" , style = 'TButton' ,
600
+ command = self .create_rve_and_plot )
601
+ button_create_rve .grid (row = 1 , column = 0 , padx = (10 , 5 ), pady = 5 , sticky = 'ew' )
602
+
603
+ button_create_ori = ttk .Button (button_frame , text = "Create Orientations" , style = 'TButton' ,
604
+ command = self .create_orientation )
605
+ button_create_ori .grid (row = 1 , column = 1 , padx = 5 , pady = 5 , sticky = 'ew' )
606
+
607
+ write_files_button = ttk .Button (button_frame , text = "Write Abaqus Input" , style = 'TButton' ,
608
+ command = self .export_abq )
609
+ write_files_button .grid (row = 2 , column = 0 , padx = (10 , 5 ), pady = 5 , sticky = 'ew' )
610
+
611
+ button_exit = ttk .Button (button_frame , text = "Exit" , style = 'TButton' , command = close )
612
+ button_exit .grid (row = 2 , column = 1 , padx = (10 , 5 ), pady = 5 , sticky = 'ew' )
613
+
614
+ def update_kernel_var (self , * args ):
615
+ self .kernel_var .set ("-" if self .texture_var .get () == 'random' else "7.5" )
616
+
617
+ def update_euler_var (self , * args ):
618
+ self .euler_var .set ("-" if self .texture_var .get () == 'random' else "0.0, 45.0, 0.0" )
619
+
620
+ def upload_ebsd (self ):
621
+ """Upload EBSD file."""
622
+ file_path = filedialog .askopenfilename (title = "Select EBSD File" , filetypes = [("EBSD Files" , "*.ang" )])
623
+ if file_path :
624
+ self_closing_message ("Uploading EBSD file, please wait.." )
625
+ self .ebsd = knpy .EBSDmap (file_path , plot = False )
626
+ self .extract_microstructure_params ()
627
+ self_closing_message ("EBSD file uploaded successfully." )
628
+ def extract_microstructure_params (self ):
629
+ """Extracts microstructure parameters from the EBSD data."""
630
+ if self .ebsd is None :
631
+ return
632
+
633
+ ms_data = self .ebsd .ms_data [0 ]
634
+ gs_param = ms_data ['gs_param' ]
635
+ ar_param = ms_data ['ar_param' ]
636
+ om_param = ms_data ['om_param' ]
637
+ self .matname_var .set (ms_data ['name' ])
638
+
639
+ def create_rve_and_plot (self ):
640
+ """Creates the RVE and plots it."""
641
+ if self .ebsd is None :
642
+ print ("No EBSD file uploaded." )
643
+ return
644
+ self_closing_message ("Creating RVE, please wait..." )
645
+ texture = self .texture_var .get ()
646
+ matname = self .matname_var .get ()
647
+ nvox = int (self .nvox_var .get ())
648
+ size = int (self .size_var .get ())
649
+ periodic = self .periodic_var .get ()
650
+
651
+ ms_data = self .ebsd .ms_data [0 ]
652
+ gs_param = ms_data ['gs_param' ]
653
+ ar_param = ms_data ['ar_param' ]
654
+ om_param = ms_data ['om_param' ]
655
+
656
+ ms_stats = knpy .set_stats (gs_param , ar_param , om_param , deq_min = 8.0 , deq_max = 19.0 , asp_min = 0.95 , asp_max = 3.5 ,
657
+ omega_min = 0.0 , omega_max = np .pi , voxels = nvox , size = size , periodicity = periodic , VF = 1.0 ,
658
+ phasename = matname , phasenum = 0 )
659
+
660
+ self .ms = knpy .Microstructure (descriptor = ms_stats , name = f"{ matname } _{ texture } _texture" )
661
+ self .ms .init_RVE ()
662
+ self .ms .pack ()
663
+ self .ms .voxelize ()
664
+ fig = self .ms .plot_voxels (silent = True , sliced = False )
665
+ self .display_plot (fig )
666
+ self_closing_message ("RVE created successfully." )
667
+
668
+ def display_plot (self , fig ):
669
+ """Displays the RVE plot."""
670
+ if self .rve_canvas is not None :
671
+ self .rve_canvas .get_tk_widget ().destroy ()
672
+
673
+ self .rve_canvas = FigureCanvasTkAgg (fig , master = self .rve_plot_frame )
674
+ self .rve_canvas .draw ()
675
+ self .rve_canvas .get_tk_widget ().pack (fill = tk .BOTH , expand = True )
676
+
677
+ def create_orientation (self ):
678
+ """Creates orientations for the grains."""
679
+ if not knpy .MTEX_AVAIL :
680
+ self_closing_message ("Generation of grain orientation requires MTEX module." )
681
+ return
682
+ self_closing_message ("The process has been started, please wait..." )
683
+
684
+ texture = self .texture_var .get ()
685
+ matname = self .matname_var .get ()
686
+
687
+ if texture == 'unimodal' :
688
+ omega = float (self .kernel_var .get ())
689
+ ang_string = self .euler_var .get ()
690
+ ang = [float (angle .strip ()) for angle in ang_string .split (',' )]
691
+ else :
692
+ omega = None
693
+ ang = None
694
+
695
+ if self .ms is None :
696
+ self_closing_message ("No RVE generated, creating RVE now." )
697
+ self .create_rve_and_plot ()
698
+
699
+ start_time = time .time ()
700
+ self .ms .generate_orientations (texture , ang = ang , omega = omega )
701
+ fig = self .ms .plot_voxels (silent = True , sliced = False , ori = True )
702
+ self .display_plot (fig )
703
+ end_time = time .time ()
704
+ duration = end_time - start_time
705
+ self_closing_message (f"Orientation created in { duration :.2f} seconds." )
706
+
707
+ def export_abq (self ):
708
+ """Exports the RVE and orientations to an Abaqus input file."""
709
+ if self .ms is None :
710
+ self_closing_message ("No RVE to export. Generating RVE without orientations." )
711
+ self .create_rve_and_plot ()
712
+
713
+ self .ms .write_abq ('v' )
714
+ self_closing_message ("Abaqus input file written successfully." )
715
+
525
716
526
717
""" Main code section """
527
718
app = tk .Tk ()
@@ -545,4 +736,5 @@ def export_abq(self):
545
736
""" Start main loop """
546
737
prve = particle_rve () # First tab: Particle-based grains
547
738
crve = cuboid_rve () # Second tab: Cuboid grains
548
- app .mainloop ()
739
+ erve = ebsd_rve () # Third tab: EBSDbased RVE
740
+ app .mainloop ()
0 commit comments