├── optimic ├── __init__.py ├── test_cases │ ├── __init__.py │ ├── bcc_3d │ │ ├── __init__.py │ │ ├── README.md │ │ └── bcc_3d_testcase.py │ ├── fcc_2d │ │ ├── __init__.py │ │ ├── README.md │ │ └── fcc_2d_testcase.py │ ├── fcc_3d │ │ ├── __init__.py │ │ ├── README.md │ │ └── fcc_3d_testcase.py │ ├── hcp_2d │ │ ├── __init__.py │ │ └── hcp_2d_testcase.py │ ├── hcp_3d │ │ ├── __init__.py │ │ └── hcp_3d_testcase.py │ ├── cubic_2d │ │ ├── __init__.py │ │ ├── README.md │ │ └── cubic_2d_testcase.py │ ├── cubic_3d │ │ ├── __init__.py │ │ ├── README.md │ │ └── cubic_3d_testcase.py │ ├── one_seed │ │ ├── __init__.py │ │ ├── README.md │ │ └── one_seed_testcase.py │ ├── random_3d │ │ ├── __init__.py │ │ ├── README.md │ │ └── random_3d_testcase.py │ ├── textural │ │ ├── __init__.py │ │ └── README.md │ └── two_seed │ │ ├── __init__.py │ │ ├── README.md │ │ └── two_seed_testcase.py ├── src │ ├── __version__.py │ ├── __init__.py │ ├── seed_spacing_files │ │ ├── __init__.py │ │ ├── import_statements.py │ │ ├── cubic_lattice_2D.py │ │ ├── fcc_lattice_2D.py │ │ ├── cubic_lattice_3D.py │ │ ├── bcc_lattice_3D.py │ │ ├── hcp_lattice_2D.py │ │ ├── hcp_lattice_3D.py │ │ └── fcc_lattice_3D.py │ ├── main_import_statements.py │ ├── set_logger.py │ ├── random_generator.py │ ├── auxiliary_files │ │ ├── 3d_plot.py │ │ └── generate_distribution.py │ ├── check_libraries.py │ ├── create_tessellations.py │ ├── create_tessellations_non_default.py │ ├── create_vtk_files.py │ └── create_obj_files.py ├── optimic └── util │ ├── user_cost_function_example3.py │ └── user_cost_function_example2.py ├── images ├── meshing.png └── tessellations.png ├── MANIFEST.in ├── run_examples.sh ├── setup.py ├── requirements.txt ├── .gitignore ├── ChangesReqd.txt └── README.md /optimic/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/bcc_3d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/fcc_2d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/fcc_3d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/hcp_2d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/hcp_3d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/cubic_2d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/cubic_3d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/one_seed/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/random_3d/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/textural/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/test_cases/two_seed/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /optimic/src/__version__.py: -------------------------------------------------------------------------------- 1 | __version__ = "v2.0" -------------------------------------------------------------------------------- /optimic/optimic: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | python -m optimic.src.main $@ 3 | -------------------------------------------------------------------------------- /images/meshing.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElsevierSoftwareX/SOFTX-D-21-00006/HEAD/images/meshing.png -------------------------------------------------------------------------------- /images/tessellations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ElsevierSoftwareX/SOFTX-D-21-00006/HEAD/images/tessellations.png -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE 2 | include requirements.txt 3 | include optimic 4 | include README.md 5 | include run_examples.sh 6 | 7 | graft images 8 | graft optimic/util 9 | -------------------------------------------------------------------------------- /run_examples.sh: -------------------------------------------------------------------------------- 1 | pip install . 2 | 3 | optimic main --size 15. 15. 15. --dimension 3 --number_seed 500 --target ./optimic/user_grain_size_distribution.txt --characteristic 0 --material example_1_3D --stress_direction 1 0 0 --seed_spacing random_3d --rand_seed 1 --optimization_method COBYLA --max_iter 2000 --number_bins 20 --mesh hex 4 | 5 | optimic main --size 180 120 15 --dimension 2 --number_seed 122 --target ./optimic/user_grain_size_distribution.txt --characteristic 2 --characteristic 5 --material example_2_2D_10k_so --stress_direction 1 0 0 --sharp_orientation 1 1 1 --seed_spacing random_3d --rand_seed 2 --optimization_method COBYLA --max_iter 10000 --number_bins 10 --user_cost_func ./optimic/util/user_cost_function_example2.py --mesh hex --mesh_size 1.0 6 | 7 | optimic main --size 10. 10. 1. --spacing_length 1 --dimension 2 --target ./optimic/junc_angle_80160_sc_17.txt --characteristic 4 --material example_3_2D_hcp_longer --stress_direction 1 0 0 --sharp_orientation 1 1 1 --seed_spacing hcp_2d --rand_seed 3 --optimization_method COBYLA --max_iter 7000 --number_bins 15 --user_cost_func ./optimic/util/user_cost_function_example3.py --mesh vis --mesh_size 0.2 -------------------------------------------------------------------------------- /optimic/src/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | __init__.py 3 | 4 | __init__.py file specify that the directory is a python package. 5 | 6 | This was created as part of "Personal Programming Project (PPP)" coursework in 7 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 8 | Germany. 9 | 10 | For reporting bugs/issues: 11 | 12 | @authors: Serrao Prince Henry, Arun Prakash 13 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 14 | created: 16 November 2019 15 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 16 | 17 | This file is part of OptiMic. 18 | 19 | OptiMic is free software: you can redistribute it and/or modify 20 | it under the terms of the GNU General Public License as published by 21 | the Free Software Foundation, either version 3 of the License, or 22 | (at your option) any later version. 23 | 24 | OptiMic is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License 30 | along with OptiMic. If not, see . 31 | 32 | """ -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/__init__.py: -------------------------------------------------------------------------------- 1 | """ 2 | __init__.py 3 | 4 | __init__.py file specify that the directory is a python package. 5 | 6 | This was created as part of "Personal Programming Project (PPP)" coursework in 7 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 8 | Germany. 9 | 10 | For reporting bugs/issues: 11 | 12 | @authors: Serrao Prince Henry, Arun Prakash 13 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 14 | created: 16 November 2019 15 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 16 | 17 | This file is part of OptiMic. 18 | 19 | OptiMic is free software: you can redistribute it and/or modify 20 | it under the terms of the GNU General Public License as published by 21 | the Free Software Foundation, either version 3 of the License, or 22 | (at your option) any later version. 23 | 24 | OptiMic is distributed in the hope that it will be useful, 25 | but WITHOUT ANY WARRANTY; without even the implied warranty of 26 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 27 | GNU General Public License for more details. 28 | 29 | You should have received a copy of the GNU General Public License 30 | along with OptiMic. If not, see . 31 | 32 | """ 33 | 34 | import numpy as np 35 | -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/import_statements.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | import_statements.py 4 | 5 | Module to import all the required libraries for all seed spacing modules. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 24 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | import matplotlib.pyplot as plt 37 | import quaternion 38 | import numba 39 | import inspect 40 | from pathlib import Path 41 | from datetime import datetime 42 | import copy 43 | # from ..__init__ import create_tessellations as create_tessellations 44 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | import os 4 | from setuptools import setup, find_packages 5 | import ast 6 | import re 7 | 8 | root_dir = os.path.abspath(os.path.join(os.path.dirname(__file__))) 9 | 10 | _version_re = re.compile(r'__version__\s+=\s+(.*)') 11 | with open(os.path.join(str(root_dir), 'optimic', 'src', '__version__.py'), 'r') as f: 12 | version = str(ast.literal_eval(_version_re.search(f.read()).group(1))) 13 | 14 | with open(os.path.join(str(root_dir), "README.md"), "r", encoding="utf-8") as fh: 15 | long_description = fh.read() 16 | 17 | setup( 18 | name='optimic', 19 | version=version, 20 | packages=find_packages(), 21 | #package_dir={'':'optimic'}, 22 | #package_data = {'': ['images/*', 'test_cases/*', 'util/*']}, 23 | url='https://gitlab.com/arun.prakash.mimm/optimic.git', 24 | license='GPLv3', 25 | author='P. H. Serrao, A. Prakash', 26 | author_email='prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de', 27 | description='A tool to generate optimized polycrystalline microstructures for materials simulations.', 28 | long_description=long_description, 29 | include_package_data=True, 30 | zip_safe=False, 31 | install_requires=[ 32 | 'numpy==1.17.4', 33 | 'scipy==1.4.1', 34 | 'matplotlib==3.0.3', 35 | 'llvmlite==0.32.1', 36 | 'numba==0.46.0', 37 | 'pytest==4.4.1', 38 | 'numpy-quaternion==2019.12.11.22.25.52', 39 | 'tess', 40 | 'click==7.0', 41 | 'gmsh-sdk==4.5.0-1', 42 | 'yappi' 43 | ], 44 | entry_points={ 45 | 'console_scripts': [ 46 | 'optimic = optimic.src.main:guide', 47 | ] 48 | }) -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | # requirements.txt 2 | # 3 | # List of required python packages. 4 | # 5 | # This was created as part of "Personal Programming Project (PPP)" coursework in 6 | # "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 7 | # Germany. 8 | # 9 | # @authors: Serrao Prince Henry, Arun Prakash 10 | # @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 11 | # created: 04 January 2021 12 | # Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 13 | # 14 | # For reporting bugs/issues: 15 | # 16 | # This file is part of OptiMic. 17 | # 18 | # OptiMic is free software: you can redistribute it and/or modify 19 | # it under the terms of the GNU General Public License as published by 20 | # the Free Software Foundation, either version 3 of the License, or 21 | # (at your option) any later version. 22 | # 23 | # OptiMic is distributed in the hope that it will be useful, 24 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 26 | # GNU General Public License for more details. 27 | # 28 | # You should have received a copy of the GNU General Public License 29 | # along with OptiMic. If not, see . 30 | 31 | 32 | 33 | ################## Please use the following command ############################ 34 | # $ pip install -r requirements.txt # 35 | ################################################################################ 36 | 37 | numpy==1.17.4 38 | scipy==1.4.1 39 | matplotlib==3.0.3 40 | numba==0.46.0 41 | pytest==4.4.1 42 | numpy-quaternion==2019.12.11.22.25.52 43 | tess 44 | click==7.0 45 | gmsh-sdk==4.5.0-1 46 | yappi==1.2.3 -------------------------------------------------------------------------------- /optimic/src/main_import_statements.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | main_import_statements.py 4 | 5 | Module to import all required libraries for other modules. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 20 December 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | import matplotlib.pyplot as plt 37 | from pathlib import Path 38 | from tess import Container 39 | import inspect 40 | from optimic.src.__version__ import __version__ as version 41 | from datetime import datetime 42 | import quaternion 43 | import numba 44 | import click 45 | import copy 46 | import scipy 47 | from scipy.stats import lognorm 48 | from scipy.optimize import minimize 49 | import matplotlib.animation as animation 50 | from time import sleep 51 | import os 52 | import importlib.util 53 | from scipy.spatial import ConvexHull 54 | import pytest 55 | import yappi 56 | import shutil 57 | import subprocess 58 | import logging 59 | import sys 60 | 61 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | *.egg-info/ 24 | .installed.cfg 25 | *.egg 26 | MANIFEST 27 | 28 | # PyInstaller 29 | # Usually these files are written by a python script from a template 30 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 31 | *.manifest 32 | *.spec 33 | 34 | # Installer logs 35 | pip-log.txt 36 | pip-delete-this-directory.txt 37 | 38 | # Unit test / coverage reports 39 | htmlcov/ 40 | .tox/ 41 | .coverage 42 | .coverage.* 43 | .cache 44 | nosetests.xml 45 | coverage.xml 46 | *.cover 47 | .hypothesis/ 48 | .pytest_cache/ 49 | 50 | # Translations 51 | *.mo 52 | *.pot 53 | 54 | # Django stuff: 55 | *.log 56 | local_settings.py 57 | db.sqlite3 58 | 59 | # Flask stuff: 60 | instance/ 61 | .webassets-cache 62 | 63 | # Scrapy stuff: 64 | .scrapy 65 | 66 | # Sphinx documentation 67 | docs/_build/ 68 | 69 | # PyBuilder 70 | target/ 71 | 72 | # Jupyter Notebook 73 | .ipynb_checkpoints 74 | 75 | # pyenv 76 | .python-version 77 | 78 | # celery beat schedule file 79 | celerybeat-schedule 80 | 81 | # SageMath parsed files 82 | *.sage.py 83 | 84 | # Environments 85 | .env 86 | .venv 87 | env/ 88 | venv/ 89 | ENV/ 90 | env.bak/ 91 | venv.bak/ 92 | 93 | # Spyder project settings 94 | .spyderproject 95 | .spyproject 96 | 97 | # Rope project settings 98 | .ropeproject 99 | 100 | # mkdocs documentation 101 | /site 102 | 103 | # mypy 104 | .mypy_cache/ 105 | 106 | # VS code 107 | .vscode 108 | 109 | ##########Latex####### 110 | 111 | *.aux 112 | *.glo 113 | *.idx 114 | *.log 115 | *.toc 116 | *.ist 117 | *.acn 118 | *.acr 119 | *.alg 120 | *.bbl 121 | *.blg 122 | *.dvi 123 | *.glg 124 | *.gls 125 | *.ilg 126 | *.ind 127 | *.lof 128 | *.lot 129 | *.maf 130 | *.mtc 131 | *.mtc1 132 | *.out 133 | *.synctex.gz 134 | -------------------------------------------------------------------------------- /optimic/src/set_logger.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | set_logger.py 4 | 5 | Module to setup and configure Python logger. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 21 May 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import logging 36 | from logging.handlers import RotatingFileHandler 37 | 38 | def set_logger(name, file_name, level_name): 39 | """ 40 | Instantiate logger module. 41 | 42 | Parameter 43 | --------- 44 | name: string 45 | Name of the current module. 46 | 47 | file_name: string 48 | Filename into which log data is to be stored. 49 | 50 | level_name: string 51 | Logger level to be used. 52 | 53 | Returns 54 | ------- 55 | Logger object. 56 | 57 | """ 58 | log = logging.getLogger(name) 59 | 60 | level_value = logging.getLevelName(level_name) 61 | log.setLevel(level_value) 62 | 63 | formatter = logging.Formatter('%(asctime)s - %(name)s - %(levelname)s - %(message)s') 64 | 65 | log_file = RotatingFileHandler(file_name, maxBytes=5*1024*1024, backupCount=3, encoding=None) 66 | log_file.setFormatter(formatter) 67 | 68 | print_handler = logging.StreamHandler() 69 | print_handler.setFormatter(formatter) 70 | 71 | if not len(log.handlers): 72 | log.addHandler(log_file) 73 | log.addHandler(print_handler) 74 | 75 | return log -------------------------------------------------------------------------------- /optimic/test_cases/one_seed/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 6: One seed** 4 | 5 | ## **Aim** 6 | 7 | To test the following: 8 | 9 | 1. Total volume of all grains 10 | 2. Periodicity of tessellations generated 11 | 12 | ## **Expected result** 13 | 14 | ### **Expected results in brief:** 15 | 16 | | Characteristic feature | Expected results | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 17 | |:--------------------------------------:|---------------------------------------------|:------------------:|:------------------:|:--------------------:|:------------------:| 18 | | Total volume of all grains | $(size\: of \: simulation \: box)^2 * length\_z$ | 100 | 100 | 100 | 100 | 19 | | Neighbors due to periodicity of tessellations generated | All neighbors must be same (cell number: 0) | 0 | 0 | 0 | 0 | 20 | 21 | ## **Command used to run the program** 22 | 23 | Please refer section 'Execute test cases' of the documentation for more details. 24 | 25 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 26 | you are in the appropriate directory, you can execute the test case using: 27 | 28 | ```bash 29 | $ ./execute test --name one_seed 30 | ``` 31 | ### **Options:** 32 | 1. `--name` refers to the test case name (cubic_2d in this case). 33 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 34 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 35 | 36 | Please refer section 'Basic usage' section for more details. 37 | 38 | ### **Parameters used** 39 | 40 | All the parameters used for this test case are enlisted below: 41 | 42 | * store_folder = "output_of_tests" 43 | * skewed_boundary_flag = False 44 | * face_flag = None 45 | * number_of_bins = 10 46 | * size_of_simulation_box = 10 47 | * spacing_lengths = [1, 2, 2.5, 5] 48 | * required_texture = np.array([1, 1, 1]) 49 | * rand_quat_flag = True 50 | * mesh_flag = 'TET' 51 | * global_mesh_size = 0.5 52 | * length_z = 1 53 | * dimension = 2 54 | * cell_number = 0 55 | * orientation_data = None 56 | 57 | ### **Files used** 58 | 59 | The test case uses all modules of the package. 60 | 61 | ## **Obtained result** 62 | 63 | The obtained results are summarized below: 64 | 65 | | Characteristic feature | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 66 | |:--------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 67 | | Total volume of all grains | 100 | 100 | 100 | 100 | 68 | | Neighbors due to periodicity of tessellations generated | 0 | 0 | 0 | 0 | 69 | 70 | 71 | The results obtained were matching with the expected results. 72 | 73 |
-------------------------------------------------------------------------------- /optimic/test_cases/random_3d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 9: Random 3D** 4 | 5 | ## **Aim** 6 | 7 | To test the following: 8 | 9 | 1. Read seeds data without orientation data from file 10 | 2. Read seeds data with orientation data from file 11 | 3. Total number of seeds 12 | 4. Total volume of all grains 13 | 14 | ## **Expected result** 15 | 16 | ### **Expected results in brief:** 17 | 18 | | Characteristic feature | Expected Result | Expected output | 19 | |:--------------------------------------------------:|:----------------------------------:|:-------------------:| 20 | | Read seeds data without orientation data from file | Original seeds data | Original seeds data | 21 | | Read seeds data with orientation data from file | Original seeds data | Original seeds data | 22 | | Total number of seeds | Total input seeds | 100 | 23 | | Total volume of all grains | $(size\: of\: simulation\: box)^3$ | 1000 | 24 | 25 | ## **Command used to run the program** 26 | 27 | Please refer section 'Execute test cases' of the documentation for more details. 28 | 29 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 30 | you are in the appropriate directory, you can execute the test case using: 31 | 32 | ```bash 33 | $ ./execute test --name random_3d 34 | ``` 35 | ### **Options:** 36 | 1. `--name` refers to the test case name (cubic_2d in this case). 37 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 38 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 39 | 40 | Please refer section 'Basic usage' section for more details. 41 | 42 | ### **Parameters used** 43 | 44 | All the parameters used for this test case are enlisted below: 45 | 46 | * store_folder = "output_of_tests" 47 | * skewed_boundary_flag = False 48 | * face_flag = None 49 | * number_of_bins = 10 50 | * size_of_simulation_box = 10 51 | * spacing_lengths = [1, 2, 2.5, 5] 52 | * required_texture = np.array([1, 1, 1]) 53 | * rand_quat_flag = True 54 | * mesh_flag = 'TET' 55 | * global_mesh_size = 0.5 56 | * dimension = 3 57 | * orientation_data = None 58 | * number_of_seeds = 100 59 | 60 | ### **Files used** 61 | 62 | The test case uses all modules of the package. 63 | 64 | ## **Obtained result** 65 | 66 | The obtained results are summarized below: 67 | 68 | | Characteristic feature | Obtained output | 69 | |:--------------------------------------------------:|:-------------------:| 70 | | Read seeds data without orientation data from file | Original seeds data | 71 | | Read seeds data with orientation data from file | Original seeds data | 72 | | Total number of seeds | 100 | 73 | | Total volume of all grains | 1000 | 74 | 75 | The results obtained were matching with the expected results. 76 | 77 |
78 | 79 | 80 | -------------------------------------------------------------------------------- /optimic/test_cases/bcc_3d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 5: BCC 3D** 4 | 5 | ## **Aim** 6 | 7 | To test the following structural characteristics: 8 | 9 | 1. Grain size of each grain 10 | 2. Number of neighbors of each grain 11 | 3. Junction lengths 12 | 4. Spacing lengths 13 | 14 | ## **Expected result** 15 | 16 | ### **Expected results in brief:** 17 | 18 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 19 | |:----------------------:|:---------------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 20 | | Grain size | 0.9847 * spacing length | 0.9847 | 1.9695 | 2.4619 | 4.9235 | 21 | | Grain size | $d = \sqrt[3]{\frac{total \: volume * 6 }{\pi * number\_of\_grains}}$ | 0.9847 | 1.9695 | 2.4619 | 4.9235 | 22 | | Number of Neighbors | 14 | 14 | 14 | 14 | 14 | 23 | | Junction length | All junctions have length and are exactly equal to $0.3536*spacing\_length$ | 0.3536 | 0.7071 | 0.884 | 1.768 | 24 | 25 | 26 | ## **Command used to run the program** 27 | 28 | Please refer section 'Execute test cases' of the documentation for more details. 29 | 30 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 31 | you are in the appropriate directory, you can execute the test case using: 32 | 33 | ```bash 34 | $ ./execute test --name bcc_3d 35 | ``` 36 | ### **Options:** 37 | 1. `--name` refers to the test case name (cubic_2d in this case). 38 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 39 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 40 | 41 | Please refer section 'Basic usage' section for more details. 42 | 43 | ### **Parameters used** 44 | 45 | All the parameters used for this test case are enlisted below: 46 | 47 | * store_folder = "output_of_tests" 48 | * skewed_boundary_flag = False 49 | * face_flag = None 50 | * number_of_bins = 10 51 | * size_of_simulation_box = 10 52 | * spacing_lengths = [1, 2, 2.5, 5] 53 | * required_texture = np.array([1, 1, 1]) 54 | * rand_quat_flag = True 55 | * mesh_flag = 'TET' 56 | * global_mesh_size = 0.5 57 | * dimension = 3 58 | * orientation_data = None 59 | 60 | ### **Files used** 61 | 62 | The test case uses all modules of the package. 63 | 64 | ## **Obtained result** 65 | 66 | The obtained results are summarized below: 67 | 68 | | Characteristic feature | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 69 | |:----------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 70 | | Grain size | 0.9847 | 1.9695 | 2.4619 | 4.9235 | 71 | | Grain size | 0.9847 | 1.9695 | 2.4619 | 4.9235 | 72 | | Number of Neighbors | 14 | 14 | 14 | 14 | 73 | | Junction length | 0.3536 | 0.7071 | 0.884 | 1.768 | 74 | 75 | The results obtained were matching with the expected results. -------------------------------------------------------------------------------- /ChangesReqd.txt: -------------------------------------------------------------------------------- 1 | Required changes to code: 2 | @auth: A. Prakash and Prince Henry Serrao 3 | @date: 25.05.2020 4 | @updated on: 18.07.2020 5 | 6 | * main.py 7 | ------------------ 8 | * line 32ff 9 | - change to new command options 10 | ## Updated with new command options[completed on 06/07/2020] 11 | 12 | * import statements 13 | - why not import as --> from abc import * 14 | ## Updated with reason for such importing style as a comment block in main.py [completed on 07/07/2020] 15 | 16 | * Function header 17 | - clearly mention each variable (both input and output), and its function 18 | 19 | * Global variables --> do you really need them? Can you not avoid them? 20 | ## Updated using Class to avoid use of Global variables [completed on 09/07/2020] 21 | 22 | - function cost_function, line 108ff --> can this be changed to numpy arrays/vectorization? 23 | ## Updated [completed on 07/07/2020] 24 | 25 | - why does the interpolation need to be done every time? 26 | ## Interpolation is needed to ensure same size of data set for comparison. 27 | 28 | line 413 --> what does the comment refer to? 29 | ## Array of all the available texture information from the research paper 30 | ## Updated. It was a redundant line and i is now removed. [completed on 06/07/2020] 31 | 32 | line 622ff - if else block can be easily avoided 33 | ## Updated [completed on 07/07/2020] 34 | 35 | TODO: 36 | - command line options could be better/informative 37 | - output formatting needs to be improved 38 | - profiler must only be activated in the debug mode ## Updated. Profiler is now only activated in debug mode [completed on 18/07/2020] 39 | - checking of libraries only to be done in the debug mode ## [completed on 09/07/2020] 40 | - Speed is currently a significant concern! 41 | 42 | 43 | * Unable to import functions from main.py directly from python 44 | ## Updated. The function 'main_run' and 'test_run' can now be imported and executed in any other python script. [completed on 17/07/2020] 45 | ## Replaced relative imports with absolute imports. [completed on 18/07/2020] 46 | ## Individual functions can now be imported in any external script or interactive python provided that 47 | the interactive instance is initiated from directory outside the package directory. This is due to 48 | fact that there are absolute import statements within modules and when instance is initiated from within 49 | the package directory, then python won't have information of the path above the top level script. [completed on 18/07/2020] 50 | 51 | ## Debug mode has been added. By default INFO log level is set for Logger. [completed on 09/07/2020] 52 | 53 | ## Add left and right padding with zeros during optimization. [completed on 11/07/2020] 54 | 55 | ## Verified that Scipy Voronoi and Tess library creates same tessellations for same seed coordinates as input. [completed on 11/07/2020] 56 | 57 | ## Using Scipy Voronoi function to create tessellations to ensure that code is modular. [completed on 11/07/2020] 58 | 59 | ## check_libraries.py can now be executed independently as well. [completed on 18/07/2020] 60 | -------------------------------------------------------------------------------- /optimic/test_cases/cubic_3d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 2: Cubic 3D** 4 | 5 | ## **Aim** 6 | 7 | To test the following structural characteristics: 8 | 9 | 1. Grain size of each grain 10 | 2. Number of neighbors of each grain 11 | 3. Grain boundary area of each grain 12 | 4. Junction lengths 13 | 5. Junction angles (in degrees) 14 | 6. Spacing lengths 15 | 16 | ## **Expected result** 17 | 18 | ### **Expected results in brief:** 19 | 20 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 21 | |:----------------------------:|:---------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 22 | | Grain size | 1.2407 * spacing length | 1.2407 | 2.4814 | 3.1017 | 6.2035 | 23 | | Grain size | $d = \sqrt[3]{\frac{total \: volume * 6 }{\pi * number\_of\_grains}}$ | 1.2407 | 2.4814 | 3.1017 | 6.2035 | 24 | | Number of Neighbors | 6 | 6 | 6 | 6 | 6 | 25 | | Grain boundary area | Each GB area = $(spacing\: length)^2$ | 1 | 4 | 6.25 | 25 | 26 | | Junction length | Equal to spacing length | 1 | 2 | 2.5 | 5 | 27 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 90° | 28 | 29 | 30 | ## **Command used to run the program** 31 | 32 | Please refer section 'Execute test cases' of the documentation for more details. 33 | 34 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 35 | you are in the appropriate directory, you can execute the test case using: 36 | 37 | ```bash 38 | $ ./execute test --name cubic_3d 39 | ``` 40 | ### **Options:** 41 | 1. `--name` refers to the test case name (cubic_2d in this case). 42 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 43 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 44 | 45 | Please refer section 'Basic usage' section for more details. 46 | 47 | ### **Parameters used** 48 | 49 | All the parameters used for this test case are enlisted below: 50 | 51 | * store_folder = "output_of_tests" 52 | * skewed_boundary_flag = False 53 | * face_flag = None 54 | * number_of_bins = 10 55 | * size_of_simulation_box = 10 56 | * spacing_lengths = [1, 2, 2.5, 5] 57 | * required_texture = np.array([1, 1, 1]) 58 | * rand_quat_flag = True 59 | * mesh_flag = 'TET' 60 | * global_mesh_size = 0.5 61 | * dimension = 3 62 | * orientation_data = None 63 | 64 | ### **Files used** 65 | 66 | The test case uses all modules of the package. 67 | 68 | ## **Obtained result** 69 | 70 | The obtained results are summarized below: 71 | 72 | | Characteristic feature | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 73 | |:----------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 74 | | Grain size | 1.2407 | 2.4814 | 3.1017 | 6.2035 | 75 | | Grain size | 1.2407 | 2.4814 | 3.1017 | 6.2035 | 76 | | Number of Neighbors | 6 | 6 | 6 | 6 | 77 | | Grain boundary area | 1 | 4 | 6.25 | 25 | 78 | | Junction length | 1 | 2 | 2.5 | 5 | 79 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 80 | 81 | The results obtained were matching with the expected results. 82 | 83 |
-------------------------------------------------------------------------------- /optimic/src/random_generator.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | random_generator.py 4 | 5 | Module to generate random seed coordinates. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | 39 | name_str = __name__ 40 | 41 | def random_generator(number_of_seeds, dimension, limits, log_level): 42 | """ 43 | Generates random numbers within the ranges from 0 to respective length of 44 | simulation box along specific axis. 45 | 46 | Parameters 47 | ---------- 48 | number_of_seeds: integer 49 | Number of seeds/grains 50 | 51 | dimension: integer 52 | Dimension of study. (2 or 3) 53 | 54 | limits: array 55 | Size of simulation box (array of length along X, Y, Z directions) 56 | 57 | log_level: string 58 | Logger level to be used. 59 | 60 | Returns 61 | ------- 62 | The function returns a list containing the coordinates of each seed. 63 | """ 64 | 65 | log = set_logger(name_str, 'log_data.log', log_level) 66 | ## Generating random numbers based on dimensions (3D or 2D) of simulation box 67 | seeds = [] 68 | length_x_axis, length_y_axis, length_z_axis = limits[:] 69 | 70 | for i in range(number_of_seeds): 71 | 72 | if dimension == 2: 73 | rand_x = np.around(np.random.uniform(low = 0, high = length_x_axis), decimals=4) 74 | rand_y = np.around(np.random.uniform(low = 0, high = length_y_axis), decimals=4) 75 | random_number_list = [rand_x, rand_y, limits[2]/2.0] 76 | seeds.append(random_number_list) 77 | 78 | elif dimension == 3: 79 | rand_x = np.around(np.random.uniform(low = 0, high = length_x_axis), decimals=4) 80 | rand_y = np.around(np.random.uniform(low = 0, high = length_y_axis), decimals=4) 81 | rand_z = np.around(np.random.uniform(low = 0, high = length_z_axis), decimals=4) 82 | random_number_list = [rand_x, rand_y, rand_z] 83 | seeds.append(random_number_list) 84 | 85 | log.info('Successfully generated random seeds') 86 | return seeds -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/cubic_lattice_2D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | cubic_lattice_2D.py 4 | 5 | Module to generate seed in Cubic lattice type of spacing in 2D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def cubic_lattice_2D(limit, a, log_level): 41 | """ 42 | Generate seeds with Cubic lattice type spacing in 2D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in cubic lattice spacing in 2D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | a: float 55 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 56 | directions in Quasi-2D case. Also the spacing_length must be a perfect 57 | divisor of size of simulation box along all three directions. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate Cubic 2D type seed spacing') 70 | 71 | seed_array = [] 72 | 73 | for x in np.arange(0, limit[0], a): 74 | for y in np.arange(0, limit[1], a): 75 | if x >= limit[0] or y >= limit[1]: 76 | continue 77 | seed_array.append([x, y, limit[2]/2.0]) 78 | 79 | seed_array = np.array(seed_array) 80 | new_array = [tuple(row) for row in seed_array] # generating tuple of each row of the seeds array 81 | seed_array_unique = np.unique(new_array, axis = 0) # removing duplicate rows to avoid overlapping seeds 82 | 83 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 84 | log.info('Cubic 2D type seed array was successfully generated') 85 | 86 | return seed_array_unique 87 | -------------------------------------------------------------------------------- /optimic/test_cases/fcc_3d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 4: FCC 3D** 4 | 5 | ## **Aim** 6 | 7 | To test the following structural characteristics: 8 | 9 | 1. Grain size of each grain 10 | 2. Number of neighbors of each grain 11 | 3. Grain boundary area of each grain 12 | 4. Junction lengths 13 | 5. Junction angles (in degrees) 14 | 6. Spacing lengths 15 | 16 | ## **Expected result** 17 | 18 | ### **Expected results in brief:** 19 | 20 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 21 | |:----------------------------:|:---------------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 22 | | Grain size | 0.7816 * spacing length | 0.7816 | 1.5632 | 1.954 | 3.908 | 23 | | Grain size | $d = \sqrt[3]{\frac{total \: volume * 6 }{\pi * number\_of\_grains}}$ | 0.7816 | 1.5632 | 1.954 | 3.908 | 24 | | Number of Neighbors | 12 | 12 | 12 | 12 | 12 | 25 | | Grain boundary area | Each GB area = $0.1768*spacing\_length*spacing\_length$ | 0.1768 | 0.7072 | 1.105 | 4.42 | 26 | | Junction length | All the junction lengths are same and are equal to $0.4330*spacing\_length$ | 0.433 | 0.866 | 1.0825 | 2.165 | 27 | | Junction angles (in degrees) | 120° | 120° | 120° | 120° | 120° | 28 | 29 | ## **Command used to run the program** 30 | 31 | Please refer section 'Execute test cases' of the documentation for more details. 32 | 33 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 34 | you are in the appropriate directory, you can execute the test case using: 35 | 36 | ```bash 37 | $ ./execute test --name fcc_3d 38 | ``` 39 | ### **Options:** 40 | 1. `--name` refers to the test case name (cubic_2d in this case). 41 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 42 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 43 | 44 | Please refer section 'Basic usage' section for more details. 45 | 46 | ### **Parameters used** 47 | 48 | All the parameters used for this test case are enlisted below: 49 | 50 | * store_folder = "output_of_tests" 51 | * skewed_boundary_flag = False 52 | * face_flag = None 53 | * number_of_bins = 10 54 | * size_of_simulation_box = 10 55 | * spacing_lengths = [1, 2, 2.5, 5] 56 | * required_texture = np.array([1, 1, 1]) 57 | * rand_quat_flag = True 58 | * mesh_flag = 'TET' 59 | * global_mesh_size = 0.5 60 | * dimension = 3 61 | * orientation_data = None 62 | 63 | ### **Files used** 64 | 65 | The test case uses all modules of the package. 66 | 67 | ## **Obtained result** 68 | 69 | The obtained results are summarized below: 70 | 71 | | Characteristic feature | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 72 | |:----------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 73 | | Grain size | 0.7816 | 1.5632 | 1.954 | 3.908 | 74 | | Grain size | 0.7816 | 1.5632 | 1.954 | 3.908 | 75 | | Number of Neighbors | 12 | 12 | 12 | 12 | 76 | | Grain boundary area | 0.1768 | 0.7072 | 1.105 | 4.42 | 77 | | Junction length | 0.433 | 0.866 | 1.0825 | 2.165 | 78 | | Junction angles (in degrees) | 120° | 120° | 120° | 120° | 79 | 80 | The results obtained were matching with the expected results. -------------------------------------------------------------------------------- /optimic/test_cases/cubic_2d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 1: Cubic 2D** 4 | 5 | ## **Aim** 6 | 7 | To test the following structural characteristics: 8 | 9 | 1. Grain size of each grain 10 | 2. Number of neighbors of each grain 11 | 3. Grain boundary area of each grain 12 | 4. Junction lengths 13 | 5. Junction angles (in degrees) 14 | 6. Spacing lengths 15 | 16 | ## **Expected result** 17 | 18 | ### **Expected results in brief:** 19 | 20 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 21 | |:----------------------------:|:---------------------------------------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 22 | | Grain size | 1.1284 * spacing length | 1.1284 | 2.2568 | 2.821 | 5.642 | 23 | | Grain size | $d = \sqrt{\frac{\frac{total \: volume}{length\: along \: Z-axis} * 4 }{\pi * number\_of\_grains}}$ | 1.1284 | 2.2568 | 2.821 | 5.642 | 24 | | Number of Neighbors | 4 | 4 | 4 | 4 | 4 | 25 | | Grain boundary area | All GB areas must be same | 1 | 2 | 2.5 | 5 | 26 | | Junction length | Equal to spacing length or length of simulation box along Z axis | 1 | 2 or 1 | 2.5 or 1 | 5 or 1 | 27 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 90° | 28 | 29 | 30 | ## **Command used to run the program** 31 | 32 | Please refer section 'Execute test cases' of the documentation for more details. 33 | 34 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 35 | you are in the appropriate directory, you can execute the test case using: 36 | 37 | ```bash 38 | $ ./execute test --name cubic_2d 39 | ``` 40 | ### **Options:** 41 | 1. `--name` refers to the test case name (cubic_2d in this case). 42 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 43 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 44 | 45 | Please refer section 'Basic usage' section for more details. 46 | 47 | ### **Parameters used** 48 | 49 | All the parameters used for this test case are enlisted below: 50 | 51 | * store_folder = "output_of_tests" 52 | * skewed_boundary_flag = False 53 | * face_flag = None 54 | * number_of_bins = 10 55 | * size_of_simulation_box = 10 56 | * spacing_lengths = [1, 2, 2.5, 5] 57 | * required_texture = np.array([1, 1, 1]) 58 | * rand_quat_flag = True 59 | * mesh_flag = 'TET' 60 | * global_mesh_size = 0.5 61 | * length_z = 1 62 | * dimension = 2 63 | * orientation_data = None 64 | 65 | ### **Files used** 66 | 67 | The test case uses all modules of the package. 68 | 69 | ## **Obtained result** 70 | 71 | The obtained results are summarized below: 72 | 73 | | Characteristic feature | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 74 | |:----------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 75 | | Grain size | 1.1284 | 2.2568 | 2.821 | 5.642 | 76 | | Grain size | 1.1284 | 2.2568 | 2.821 | 5.642 | 77 | | Number of Neighbors | 4 | 4 | 4 | 4 | 78 | | Grain boundary area | 1 | 2 | 2.5 | 5 | 79 | | Junction length | 1 | 2 or 1 | 2.5 or 1 | 5 or 1 | 80 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 81 | 82 | The results obtained were matching with the expected results. 83 | 84 |
85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /optimic/test_cases/one_seed/one_seed_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | one_seed_testcase.py 4 | 5 | Module to test some features of program for one seed. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def one_seed_testcase(tessellation, cell_number, size_of_simulation_box, length_z, log_level): 41 | """ 42 | Execute all assert statements related to one_seed_testcase. 43 | 44 | Parameters 45 | ---------- 46 | tessellation: dictionary 47 | Dictionary of tessellations data with following keys: 48 | 1. number_of_grains 49 | 2. number_of_faces_list 50 | 3. vertices_list 51 | 4. face_vertices_list 52 | 5. centroid_list 53 | 6. volume_list 54 | 7. normals_list 55 | 8. neighbors_list 56 | 9. face_area_list 57 | 10. number_of_edges_list 58 | 59 | cell_number: integer 60 | Grain number.(Since only 1 grain, it must be always 0) 61 | 62 | size_of_simulation_box: array of length 3 63 | Size of simulation box (array of length along X, Y, Z directions) 64 | 65 | length_z: float 66 | Size of simulation box along Z axis. 67 | 68 | log_level: string 69 | Logger level to be used. 70 | 71 | Returns 72 | ------- 73 | Function returns nothing. 74 | """ 75 | 76 | log = set_logger(name_str, 'log_data.log', log_level) 77 | total_volume = 0 # initializing the variable 78 | neighbors = tessellation['neighbors_list'][cell_number] # storing the neighbors of the specified cell 79 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 80 | total_volume += copy.deepcopy(tessellation['volume_list'][v]) # updating the total_volume variable 81 | 82 | try: 83 | assert np.isclose(total_volume, size_of_simulation_box*size_of_simulation_box*length_z) ## Testing for total volume of all cells 84 | assert np.isclose(np.count_nonzero(neighbors), 0) ## Testing periodicity 85 | except AssertionError: 86 | log.exception('one_seed_testcase failed !!') 87 | 88 | log.info('one_seed_testcase passed !!') -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/fcc_lattice_2D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | fcc_lattice_2D.py 4 | 5 | Module to generate seed in Face Centered Cubic (FCC) lattice type of spacing in 2D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def fcc_lattice_2D(limit, a, log_level): 41 | """ 42 | Generate seeds with FCC lattice type spacing in 2D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in FCC lattice spacing in 2D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | a: float 55 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 56 | directions in Quasi-2D case. Also the spacing_length must be a perfect 57 | divisor of size of simulation box along all three directions. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate FCC 2D type seed spacing') 70 | 71 | ## Generating an empty list to store seed coordinates 72 | seed_array = [] 73 | 74 | ## Generating regular grid seeds array 75 | ## Iterating in all directions 76 | for x in np.arange(0, limit[0], a): 77 | for y in np.arange(0, limit[1], a): 78 | if x >= limit[0] or y >= limit[0]: 79 | continue 80 | seed_array.append([x, y, limit[2]/2.0]) 81 | 82 | if x < limit[0] and y < limit[1]: 83 | seed_array.append([x + a/2, y + a/2, limit[2]/2.0]) 84 | 85 | seed_array = np.array(seed_array) 86 | ## Checking for uniqueness of all seeds 87 | new_array = [tuple(row) for row in seed_array] 88 | seed_array_unique = np.unique(new_array, axis = 0) 89 | 90 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 91 | log.info('FCC 2D type seed array was successfully generated') 92 | 93 | return seed_array_unique 94 | -------------------------------------------------------------------------------- /optimic/src/auxiliary_files/3d_plot.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | 3d_plot.py 4 | 5 | Module to generate 3d plot. It has to be modified based on needs 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 19 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | import matplotlib.pyplot as plt 37 | from mpl_toolkits.mplot3d import Axes3D 38 | 39 | size_of_simulation_box = 2.6 40 | a = 1.3 41 | limit = np.array([size_of_simulation_box, size_of_simulation_box, size_of_simulation_box]) 42 | seed_array = np.zeros([2*((int(limit[0])) * (int(limit[1])) + (int(limit[1]) * int(limit[2])) + (int(limit[0]) * int(limit[2])) + (int(limit[0])*int(limit[1])*int(limit[2])*3)), 3]) 43 | dimension = 3 44 | material = "FCC_3D" 45 | 46 | seed_array = np.zeros([2*((int(limit[0])) * (int(limit[1])) + (int(limit[1]) * int(limit[2])) + (int(limit[0]) * int(limit[2])) + (int(limit[0])*int(limit[1])*int(limit[2])*3)), 3]) 47 | 48 | ## Generating regular grid seeds array 49 | counter = 0 50 | for x in np.linspace(0, limit[0], limit[0]/a +1): 51 | for y in np.linspace(0, limit[1], limit[1]/a +1): 52 | for z in np.linspace(0, limit[2], limit[2]/a +1): 53 | 54 | if a*x >= limit[0] or a*y >= limit[1] or a*z >= limit[2]: 55 | continue 56 | seed_array[counter, 0] = x 57 | seed_array[counter, 1] = y 58 | seed_array[counter, 2] = z 59 | counter += 1 60 | 61 | if x + a/2 <= limit[0] and y + a/2 <= limit[1]: 62 | seed_array[counter, 0] = x + a/2 63 | seed_array[counter, 1] = y + a/2 64 | seed_array[counter, 2] = z 65 | counter += 1 66 | 67 | if y + a/2 <= limit[1] and z + a/2 <= limit[2]: 68 | seed_array[counter, 0] = x 69 | seed_array[counter, 1] = y + a/2 70 | seed_array[counter, 2] = z + a/2 71 | counter += 1 72 | 73 | if x + a/2 <= limit[0] and z + a/2 <= limit[2]: 74 | seed_array[counter, 0] = x + a/2 75 | seed_array[counter, 1] = y 76 | seed_array[counter, 2] = z + a/2 77 | counter += 1 78 | 79 | new_array = [tuple(row) for row in seed_array] 80 | seed_array_unique = np.unique(new_array, axis = 0) 81 | 82 | fig = plt.figure(figsize=(10,10)) 83 | ax = Axes3D(fig) 84 | 85 | ax.scatter(seed_array_unique[:, 0], seed_array_unique[:, 1], seed_array_unique[:, 2]) 86 | 87 | fig, ax = plt.subplots() 88 | ax.scatter(seed_array_unique[:, 0], seed_array_unique[:, 1]) 89 | plt.show() -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/cubic_lattice_3D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | cubic_lattice_3D.py 4 | 5 | Module to generate seed in Cubic lattice type of spacing in 3D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def cubic_lattice_3D(limit, a, log_level): 41 | """ 42 | Generate seeds with Cubic lattice type spacing in 3D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in cubic lattice spacing in 3D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | a: float 55 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 56 | directions in Quasi-2D case. Also the spacing_length must be a perfect 57 | divisor of size of simulation box along all three directions. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate Cubic 3D type seed spacing') 70 | 71 | ## Generating an array to store seed coordinates 72 | seed_array = np.zeros([(int(np.ceil(limit[0]/a)) + 1) * (int(np.ceil(limit[1]/a)) + 1) * (int(np.ceil(limit[2]/a)) + 1), 3]) 73 | counter = 0 74 | 75 | ## Iterating in all directions 76 | for x in np.arange(0, limit[0], a): 77 | for y in np.arange(0, limit[1], a): 78 | for z in np.arange(0, limit[2], a): 79 | 80 | if x >= limit[0] or y >= limit[1] or z >= limit[2]: 81 | continue 82 | seed_array[counter, 0] = x 83 | seed_array[counter, 1] = y 84 | seed_array[counter, 2] = z 85 | counter += 1 86 | 87 | ## Checking for uniqueness of all seeds 88 | new_array = [tuple(row) for row in seed_array] 89 | seed_array_unique = np.unique(new_array, axis = 0) 90 | 91 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 92 | log.info('Cubic 3D type seed array was successfully generated') 93 | 94 | return seed_array_unique -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/bcc_lattice_3D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | bcc_lattice_3D.py 4 | 5 | Module to generate seed in Body Centered Cubic (BCC) type of spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def bcc_lattice_3D(limit, a, log_level): 41 | """ 42 | Generate seeds with BCC lattice type spacing in 3D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in BCC spacing and ensures that there is no 47 | overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | a: float 55 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 56 | directions in Quasi-2D case. Also the spacing_length must be a perfect 57 | divisor of size of simulation box along all three directions. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate BCC type seed spacing') 70 | 71 | ## Generating an empty list to store seed coordinates 72 | seed_array = [] 73 | 74 | ## Generating regular grid seeds array 75 | ## Iterating in all directions 76 | for x in np.arange(0, limit[0], a): 77 | for y in np.arange(0, limit[1], a): 78 | for z in np.arange(0, limit[2], a): 79 | if x >= limit[0] or y >= limit[1] or z >= limit[2]: # Checking if the current position is outside limits 80 | continue 81 | seed_array.append([x, y, z]) 82 | 83 | if x < limit[0] and y < limit[1] and z < limit[2]: # Placing the body centered seed 84 | seed_array.append([x + a/2, y + a/2, z + a/2]) 85 | 86 | seed_array = np.array(seed_array) 87 | ## Checking for uniqueness of all seeds 88 | new_array = [tuple(row) for row in seed_array] 89 | seed_array_unique = np.unique(new_array, axis = 0) 90 | 91 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 92 | log.info('BCC type seed array was successfully generated') 93 | 94 | return seed_array_unique -------------------------------------------------------------------------------- /optimic/util/user_cost_function_example3.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | user_cost_function_5_junc_angle.py 4 | 5 | Module to demonstrate an example of user-defined cost function. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | 37 | def function_formula(combined_user_data, combined_predicted_data, start_row_combined_data, data_dictionary, args): 38 | """ 39 | Calculating cost value using Sum of Squared Error (SSE) between the 40 | predicted data and the user data and scaling it with a factor of 100. 41 | 42 | Parameters 43 | ---------- 44 | combined_user_data: array 45 | Distribution of user defined data for all characteristics. 46 | 47 | combined_predicted_data: array 48 | Distribution of predicted data for all characteristics. 49 | 50 | start_row_combined_data: list 51 | List comprising of row indexes of user and predicted data associated 52 | with each characteristic to be optimized. 53 | 54 | data_dictionary: dictionary 55 | Dictionary consisting of complete data pertaining to characteristic to 56 | be optimized. Keys used in the dictionary are integers used for 57 | identifying appropriate characteristics as below: 58 | '0': Grain sizes 59 | '1': Number of neighbors 60 | '2': Grain boundary areas 61 | '3': Junction lengths 62 | '4': Junction angles in degrees 63 | '5a': Distance between grains as 1D array 64 | '5b': Distance between grains as matrix array 65 | '6': Disorientation angles 66 | '7': Type of grain boundaries 67 | '8': Schmid factors 68 | 69 | args: list 70 | Common arguments consisting of following: 71 | 1. parameter_list 72 | 2. dimension 73 | 3. user_data 74 | 4. start_row_of_parameter 75 | 5. limit 76 | 6. number_of_bins 77 | 7. fig_animate 78 | 8. ax_animate 79 | 9. cost_function_names 80 | 10. func_name_key 81 | 11. required_texture 82 | 12. rand_quat_flag 83 | 13. stress_direction 84 | 14. orientation_data 85 | 15. skewed_boundary_flag 86 | 16. tessellation (DICTIONARY OF ALL TESSELLATION DATA) 87 | 88 | Returns 89 | ------- 90 | Scalar scaled SSE cost value. 91 | """ 92 | user_y = combined_user_data[:, 1] 93 | predicted_y = combined_predicted_data[:, 1] 94 | value = (np.sum(np.square((user_y - predicted_y)*100))) # 100 is multiplied so that the data is scaled for appropriate optimization 95 | return value -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/hcp_lattice_2D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | hcp_lattice_2D.py 4 | 5 | Module to generate seed in HCP lattice type of spacing in 2D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def hcp_lattice_2D(limit, spacing_length, log_level): 41 | """ 42 | Generate seeds with HCP lattice type spacing in 2D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in hcp lattice spacing in 2D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | spacing_length: float 55 | Spacing between seeds along X direction. Spacing_length is a factor 56 | multiplied to SQRT(3) in Y & Z directions in 3D case and along Y 57 | directions in Quasi-2D case. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate HCP 2D type seed spacing') 70 | 71 | x_limit, y_limit, z_limit = limit 72 | seed_array = np.zeros([int(np.ceil(x_limit/spacing_length) * (2*np.ceil(y_limit/(np.sqrt(3)*spacing_length)))), 3]) # sqrt(3) is due to spacing of seeds in HCP 73 | seed_array[:, 2] = z_limit/2.0 74 | 75 | counter = 0 76 | for x in np.arange(0, x_limit, spacing_length): 77 | for y in np.arange(0, y_limit, np.sqrt(3)*spacing_length): 78 | 79 | if (x >= x_limit) or (y >= y_limit): 80 | continue 81 | 82 | seed_array[counter, :2] = x, y 83 | counter += 1 84 | 85 | seed_array[counter, 0] = x + (spacing_length/2) 86 | seed_array[counter, 1] = y + (np.sqrt(3)*spacing_length/2) 87 | counter += 1 88 | 89 | new_array = [tuple(row) for row in seed_array] # generating tuple of each row of the seeds array 90 | seed_array_unique = np.unique(new_array, axis = 0) # removing duplicate rows to avoid overlapping seeds 91 | 92 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 93 | log.info('HCP 2D type seed array was successfully generated') 94 | 95 | return seed_array_unique 96 | -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/hcp_lattice_3D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | hcp_lattice_3D.py 4 | 5 | Module to generate seed in HCP lattice type of spacing in 3D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def hcp_lattice_3D(limit, spacing_length, log_level): 41 | """ 42 | Generate seeds with HCP lattice type spacing in 3D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in HCP lattice spacing in 3D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | spacing_length: float 55 | Spacing between seeds along X direction. Spacing_length is a factor 56 | multiplied to SQRT(3) in Y & Z directions in 3D case and along Y 57 | directions in Quasi-2D case. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate HCP 3D type seed spacing') 70 | 71 | x_limit, y_limit, z_limit = limit 72 | seed_array = np.zeros([int(np.ceil(x_limit/spacing_length) * (2*np.ceil(y_limit/(np.sqrt(3)*spacing_length))) * (2*np.ceil(z_limit/(np.sqrt(3)*spacing_length)))), 3]) # sqrt(3) is due to spacing of seeds in HCP 73 | 74 | counter = 0 75 | for x in np.arange(0, x_limit, spacing_length): 76 | for y in np.arange(0, y_limit, np.sqrt(3)*spacing_length): 77 | for z in np.arange(0, z_limit, spacing_length): 78 | if (x >= x_limit) or (y >= y_limit) or (y >= z_limit): 79 | continue 80 | seed_array[counter, :] = x, y, z 81 | counter += 1 82 | 83 | seed_array[counter, 0] = x + (spacing_length/2) 84 | seed_array[counter, 1] = y + (np.sqrt(3)*spacing_length/2) 85 | seed_array[counter, 2] = z + (spacing_length/2) 86 | counter += 1 87 | 88 | new_array = [tuple(row) for row in seed_array] # generating tuple of each row of the seeds array 89 | seed_array_unique = np.unique(new_array, axis = 0) # removing duplicate rows to avoid overlapping seeds 90 | 91 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 92 | log.info('HCP 3D type seed array was successfully generated') 93 | 94 | return seed_array_unique 95 | -------------------------------------------------------------------------------- /optimic/test_cases/fcc_2d/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 3: FCC 2D** 4 | 5 | ## **Aim** 6 | 7 | To test the following structural characteristics: 8 | 9 | 1. Grain size of each grain 10 | 2. Number of neighbors of each grain 11 | 3. Grain boundary area of each grain 12 | 4. Junction lengths 13 | 5. Junction angles (in degrees) 14 | 6. Spacing lengths 15 | 16 | ## **Expected result** 17 | 18 | ### **Expected results in brief:** 19 | 20 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 21 | |:----------------------------:|:---------------------------------------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 22 | | Grain size | 0.7979 * spacing length | 0.7979 | 1.5958 | 1.9947 | 3.9895 | 23 | | Grain size | $d = \sqrt{\frac{\frac{total \: volume}{length\: along \: Z-axis} * 4 }{\pi * number\_of\_grains}}$ | 0.7979 | 1.5958 | 1.9947 | 3.9895 | 24 | | Number of Neighbors | 4 | 4 | 4 | 4 | 4 | 25 | | Grain boundary area | All GB areas must be same and must be equal to $0.7071*spacing\_length*length\_z$ | 0.7071 | 1.4142 | 1.7677 | 3.5355 | 26 | | Junction length | All junction lengths must be equal to $0.7071*spacing\_length$ or length_z | 0.7071 or 1 | 1.4142 or 1 | 1.7677 or 1 | 3.5355 or 1 | 27 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 90° | 28 | 29 | 30 | ## **Command used to run the program** 31 | 32 | Please refer section 'Execute test cases' of the documentation for more details. 33 | 34 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 35 | you are in the appropriate directory, you can execute the test case using: 36 | 37 | ```bash 38 | $ ./execute test --name fcc_2d 39 | ``` 40 | ### **Options:** 41 | 1. `--name` refers to the test case name (cubic_2d in this case). 42 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 43 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 44 | 45 | Please refer section 'Basic usage' section for more details. 46 | 47 | ### **Parameters used** 48 | 49 | All the parameters used for this test case are enlisted below: 50 | 51 | * store_folder = "output_of_tests" 52 | * skewed_boundary_flag = False 53 | * face_flag = None 54 | * number_of_bins = 10 55 | * size_of_simulation_box = 10 56 | * spacing_lengths = [1, 2, 2.5, 5] 57 | * required_texture = np.array([1, 1, 1]) 58 | * rand_quat_flag = True 59 | * mesh_flag = 'TET' 60 | * global_mesh_size = 0.5 61 | * length_z = 1 62 | * dimension = 2 63 | * orientation_data = None 64 | 65 | ### **Files used** 66 | 67 | The test case uses all modules of the package. 68 | 69 | ## **Obtained result** 70 | 71 | The obtained results are summarized below: 72 | 73 | | Characteristic feature | Expected Result | Spacing length = 1 | Spacing length = 2 | Spacing length = 2.5 | Spacing length = 5 | 74 | |:----------------------------:|:---------------------------------------------------------------------------------------------------:|:------------------:|:------------------:|:--------------------:|:------------------:| 75 | | Grain size | 0.7979 * spacing length | 0.7979 | 1.5958 | 1.9947 | 3.9895 | 76 | | Grain size | $d = \sqrt{\frac{\frac{total \: volume}{length\: along \: Z-axis} * 4 }{\pi * number\_of\_grains}}$ | 0.7979 | 1.5958 | 1.9947 | 3.9895 | 77 | | Number of Neighbors | 4 | 4 | 4 | 4 | 4 | 78 | | Grain boundary area | All GB areas must be same and must be equal to $0.7071*spacing\_length*length\_z$ | 0.7071 | 1.4142 | 1.7677 | 3.5355 | 79 | | Junction length | All junction lengths must be equal to $0.7071*spacing\_length$ or length_z | 0.7071 or 1 | 1.4142 or 1 | 1.7677 or 1 | 3.5355 or 1 | 80 | | Junction angles (in degrees) | 90° | 90° | 90° | 90° | 90° | 81 | 82 | The results obtained were matching with the expected results. 83 | 84 |
85 | -------------------------------------------------------------------------------- /optimic/src/seed_spacing_files/fcc_lattice_3D.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | fcc_lattice_3D.py 4 | 5 | Module to generate seed in Face Centered Cubic (FCC) lattice type of spacing in 3D. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 04 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.seed_spacing_files.import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def fcc_lattice_3D(limit, a, log_level): 41 | """ 42 | Generate seeds with FCC lattice type spacing in 3D. 43 | 44 | Processing 45 | ---------- 46 | The function generates seeds in FCC lattice spacing in 3D and ensures 47 | that there is no overlapping of seeds at the extreme ends of simulation box. 48 | 49 | Parameters 50 | ---------- 51 | limit: array 52 | Size of simulation box (array of length along X, Y, Z directions) 53 | 54 | a: float 55 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 56 | directions in Quasi-2D case. Also the spacing_length must be a perfect 57 | divisor of size of simulation box along all three directions. 58 | 59 | log_level: string 60 | Logger level to be used. 61 | 62 | Returns 63 | ------- 64 | The function returns an array of regularly spaced seeds and also ensures 65 | that the seeds are unique. 66 | """ 67 | 68 | log = set_logger(name_str, 'log_data.log', log_level) 69 | log.info('Starting to generate FCC 3D type seed spacing') 70 | 71 | ## Generating an empty list to store seed coordinates 72 | seed_array = [] 73 | 74 | ## Generating regular grid seeds array 75 | ## Iterating in all directions 76 | for x in np.arange(0, limit[0], a): 77 | for y in np.arange(0, limit[1], a): 78 | for z in np.arange(0, limit[2], a): 79 | 80 | if x >= limit[0] or y >= limit[1] or z >= limit[2]: 81 | continue 82 | 83 | seed_array.append([x, y, z]) 84 | 85 | if x + a/2 <= limit[0] and y + a/2 <= limit[1]: 86 | seed_array.append([x + a/2, y + a/2, z]) 87 | 88 | if y + a/2 <= limit[1] and z + a/2 <= limit[2]: 89 | seed_array.append([x, y + a/2, z + a/2]) 90 | 91 | if x + a/2 <= limit[0] and z + a/2 <= limit[2]: 92 | seed_array.append([x + a/2, y, z + a/2]) 93 | 94 | seed_array = np.array(seed_array) 95 | 96 | ## Checking for uniqueness of all seeds 97 | new_array = [tuple(row) for row in seed_array] 98 | seed_array_unique = np.unique(new_array, axis = 0) 99 | 100 | log.debug('Generated seeds array is ' + str(seed_array_unique)) 101 | log.info('FCC 3D type seed array was successfully generated') 102 | 103 | return seed_array_unique -------------------------------------------------------------------------------- /optimic/src/auxiliary_files/generate_distribution.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | generate_distribution.py 4 | 5 | Module to generate lognormal, Gauss normal and gamma distribution. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 24 January 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | import matplotlib.pyplot as plt 37 | from scipy.stats import lognorm 38 | from scipy.stats import norm 39 | from scipy.stats import gamma 40 | 41 | ## Parameters for distribution 42 | s = 0.945 43 | a = 2 44 | loc = 40 45 | scale = 4 46 | x = np.linspace(0, 10, 1000) 47 | x_disorientation = np.linspace(0, 60, 1000) 48 | 49 | ## Generating distribution 50 | distribution_lognormal = lognorm.pdf(x, s, loc=1) 51 | distribution_gaussian = norm.pdf(x_disorientation, loc = loc, scale = scale) 52 | distribution_gamma = gamma.pdf(x, a) 53 | 54 | ## Storing lognorm distribution to an array 55 | data_array = np.zeros([len(x), 2]) 56 | data_array[:, 0] = np.around(x[:], decimals=4) 57 | data_array[:, 1] = np.around(distribution_lognormal, decimals=4) 58 | 59 | ## Storing gaussian distribution to array 60 | data_array_gauss = np.zeros([len(x), 2]) 61 | data_array_gauss[:, 0] = np.around(x_disorientation[:], decimals=4) 62 | data_array_gauss[:, 1] = np.around(distribution_gaussian, decimals=4) 63 | 64 | ## Storing gamma distribution to array 65 | data_array_gamma = np.zeros([len(x), 2]) 66 | data_array_gamma[:, 0] = np.around(x[:], decimals=4) 67 | data_array_gamma[:, 1] = np.around(distribution_gamma, decimals=4) 68 | 69 | ## Checking if the total probability (area under curve) is 1 70 | print((np.sum((data_array[1:, 0] - data_array[:-1, 0]) * data_array[:-1, 1]))) 71 | assert np.isclose((np.sum((data_array[1:, 0] - data_array[:-1, 0]) * data_array[:-1, 1])), 1, atol=1e-1) 72 | assert np.isclose((np.sum((data_array_gauss[1:, 0] - data_array_gauss[:-1, 0]) * data_array_gauss[:-1, 1])), 1, atol=1e-1) 73 | assert np.isclose((np.sum((data_array_gamma[1:, 0] - data_array_gamma[:-1, 0]) * data_array_gamma[:-1, 1])), 1, atol=1e-1) 74 | 75 | 76 | ## Writing the generated distribution to file 77 | with open('user_distribution.txt', 'a+') as f: 78 | f.truncate(0) 79 | f.write('# Grain Sizes, Frequency of Grain Sizes \n') 80 | np.savetxt(f, data_array, delimiter=',', fmt= '%.4f') 81 | f.write('end\n') 82 | f.write('# Disorientation_angles, Frequency of disorientation angles \n') 83 | np.savetxt(f, data_array_gauss, delimiter=',', fmt= '%.4f') 84 | f.write('end\n') 85 | f.write('# Distance between grains, Frequency of distances \n') 86 | np.savetxt(f, data_array_gamma, delimiter=',', fmt= '%.4f') 87 | f.write('end\n') 88 | 89 | ## Plotting 90 | fig, ax = plt.subplots() 91 | ax.plot(x, distribution_lognormal, 92 | 'r-', lw=5, alpha=0.6, label='lognorm pdf') 93 | ax.plot(x_disorientation, distribution_gaussian, 94 | 'y-', lw=5, alpha=0.6, label='gaussian pdf') 95 | ax.plot(x, distribution_gamma, 96 | 'b-', lw=5, alpha=0.6, label='gamma pdf') 97 | 98 | plt.legend() 99 | plt.show() -------------------------------------------------------------------------------- /optimic/src/check_libraries.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | check_libraries.py 4 | 5 | Module to ensure installation of all required python libraries. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 19 May 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | """ 33 | 34 | import os 35 | from optimic.src.set_logger import set_logger 36 | name_str = __name__ 37 | 38 | def check_import(name, install_command): 39 | """ 40 | Checks if a certain library is installed and installs them if it isn't 41 | installed. 42 | 43 | Parameter 44 | --------- 45 | name: string 46 | Name of the library 47 | install_command: string 48 | Command-line input required to install a library 49 | 50 | Returns 51 | ------- 52 | Function returns nothing. 53 | """ 54 | try: 55 | __import__(name) 56 | except ImportError: 57 | log.exception('Failed importing ' + name + ' library.') 58 | input_text = input("Do you want to install " + name + " ? [Yes/No] \n").lower() 59 | if 'y' in input_text: 60 | os.system(install_command) 61 | else: 62 | log.critical("Since required library " + name +" is not installed, program will exit now. \n") 63 | exit() 64 | 65 | def check_libraries(log_level): 66 | """ 67 | Iterates through the list of all required libraries and installs them if 68 | they aren't installed. 69 | 70 | Parameter 71 | --------- 72 | log_level: string 73 | Logger level to be used. 74 | """ 75 | log = set_logger(name_str, 'log_data.log', log_level) 76 | 77 | library_list = ['pip', 'numpy', 'scipy', 'matplotlib', 'numba', 'pytest', 'quaternion', 'tess', 'click', 'gmsh', 'yappi'] 78 | install_command = {'os': ' ', 79 | 'pip': 'curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py; python get-pip.py', 80 | 'numpy': 'pip install numpy', 81 | 'scipy': 'pip install scipy', 82 | 'matplotlib': 'pip install matplotlib', 83 | 'numba': 'pip install numba', 84 | 'pytest': 'pip install pytest==4.4.1', 85 | 'quaternion': 'pip install numpy-quaternion==2019.12.11.22.25.52', 86 | 'tess': 'pip install tess', 87 | 'click': 'pip install click==7.0', 88 | 'gmsh': 'pip install gmsh-sdk==4.5.0-1; echo -e "Please refer http://gmsh.info/ for installation of GMSH software. GMSH software is required for working of meshing functionality. \nFor ubuntu based systems, GMSH can be installed using following command: \n $ sudo apt-get update; sudo apt-get install gmsh"', 89 | 'yappi': 'pip install yappi==1.2.3'} 90 | for name in library_list: 91 | log.info("Checking for " + name + " library.") 92 | check_import(name, install_command[name]) 93 | 94 | log.info("All required libraries are installed.") 95 | 96 | if __name__ == '__main__': 97 | check_libraries('DEBUG') -------------------------------------------------------------------------------- /optimic/src/create_tessellations.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | create_tessellations.py 4 | 5 | Module to perform voronoi tessellations using 'Tess' package 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | from optimic.src.main_import_statements import * 35 | 36 | from optimic.src.set_logger import set_logger 37 | 38 | name_str = __name__ 39 | 40 | def create_tessellations(seed_array, limit, log_level): #x are seed coordinates, y are limits 41 | """ 42 | Create tessellations with Periodicity to be True by default. 43 | 44 | Parameters 45 | ---------- 46 | seed_array: array 47 | Array of seed coordinates in 3D. 48 | 49 | limit: array 50 | Size of simulation box along X, Y & Z direction. 51 | 52 | log_level: string 53 | Logger level to be used. 54 | 55 | Returns 56 | ------- 57 | Dictionary of tessellations data with following keys: 58 | 1. number_of_grains 59 | 2. number_of_faces_list 60 | 3. vertices_list 61 | 4. face_vertices_list 62 | 5. centroid_list 63 | 6. volume_list 64 | 7. normals_list 65 | 8. neighbors_list 66 | 9. face_area_list 67 | 10. number_of_edges_list 68 | """ 69 | log = set_logger(__name__, 'log_data.log', log_level) 70 | log.debug('Tessellations are to be created with limits as ' + str(limit) + ' and seed array as:\n' + str(seed_array)) 71 | 72 | local_tessellation = Container(seed_array, limits=limit, periodic = True) 73 | 74 | log.info('Tessellations were created successfully.') 75 | 76 | number_of_grains = len(local_tessellation) 77 | number_of_faces_list = [v.number_of_faces() for v in local_tessellation] 78 | vertices_list = [v.vertices() for v in local_tessellation] 79 | face_vertices_list = [v.face_vertices() for v in local_tessellation] 80 | centroid_list = [v.centroid() for v in local_tessellation] 81 | volume_list = [v.volume() for v in local_tessellation] 82 | normals_list = [v.normals() for v in local_tessellation] 83 | neighbors_list = [v.neighbors() for v in local_tessellation] 84 | face_area_list = [v.face_areas() for v in local_tessellation] 85 | number_of_edges_list = [v.number_of_edges() for v in local_tessellation] 86 | 87 | tessellation = {} 88 | tessellation['number_of_grains'] = number_of_grains 89 | tessellation['number_of_faces_list'] = number_of_faces_list 90 | tessellation['vertices_list'] = vertices_list 91 | tessellation['face_vertices_list'] = face_vertices_list 92 | tessellation['centroid_list'] = centroid_list 93 | tessellation['volume_list'] = volume_list 94 | tessellation['normals_list'] = normals_list 95 | tessellation['neighbors_list'] = neighbors_list 96 | tessellation['face_area_list'] = face_area_list 97 | tessellation['number_of_edges_list'] = number_of_edges_list 98 | 99 | log.info('All required properties of created tessellations are stored in the dictionary successfully.') 100 | 101 | return tessellation # returns list of cells as class instances -------------------------------------------------------------------------------- /optimic/test_cases/textural/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 8: Textural** 4 | 5 | ## **Aim** 6 | 7 | To test the following textural characteristics: 8 | 9 | * 'sharp_texture_quaternions' function returns unit quaternions 10 | * Disorientation Angles 11 | * Maximum value of disorientation angles 12 | * Grains with same orientations 13 | * Schmid Factor 14 | * Maximum value of Schmid factor 15 | * Schmid Factor for known stress directions 16 | * Known misorientation data 17 | 18 | ## **Expected result** 19 | 20 | ### **Expected results in brief:** 21 | 22 | | Characteristic feature | Expected Result | 23 | |:-------------------------------------------------------:|:-------------------------:| 24 | | Norm of sharp texture quaternions | 1 | 25 | | Maximum value of disorientation angles | <= 62.8 | 26 | | Disorientation angles for grains with same orientations | All angles are equal to 0 | 27 | | Maximum value of Schmid factor | <= 0.5 | 28 | 29 | The following table shows the heighest schmid factor for the known stress directions: 30 | 31 | | **Stress Direction [X, Y, Z]** | **Highest Schmid factor** | 32 | |:------------------------------:|:-------------------------:| 33 | | [1, -1, 0] | 0.408 | 34 | | [1, 0, 0] | 0.408 | 35 | | [1, 1, 0] | 0.408 | 36 | 37 | **Known misorientation data** 38 | 39 | The misorientation data (angle, axis and GB type) is based on the data given in *'The measurement of Grain Boundary geometry', V Randle, Institute of Physics (IOP) Publishing, 1993,* Page No. 40-43, Table 3.3. 40 | 41 | The misorientation axis data is then tested to ensure that all the GB types along with its corresponding misorientation angles and axes has been captured. 42 | 43 | ## **Command used to run the program** 44 | 45 | Please refer section 'Execute test cases' of the documentation for more details. 46 | 47 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 48 | you are in the appropriate directory, you can execute the test case using: 49 | 50 | ```bash 51 | $ ./execute test --name textural 52 | ``` 53 | ### **Options:** 54 | 1. `--name` refers to the test case name (cubic_2d in this case). 55 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 56 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 57 | 58 | Please refer section 'Basic usage' section for more details. 59 | 60 | ### **Parameters used** 61 | 62 | All the parameters used for this test case are enlisted below: 63 | 64 | * store_folder = "output_of_tests" 65 | * skewed_boundary_flag = False 66 | * face_flag = None 67 | * number_of_bins = 10 68 | * size_of_simulation_box = 10 69 | * spacing_lengths = [1, 2, 2.5, 5] 70 | * required_texture = np.array([1, 1, 1]) 71 | * rand_quat_flag = True 72 | * mesh_flag = 'TET' 73 | * global_mesh_size = 0.5 74 | * length_z = 1 75 | * dimension = 2 76 | 77 | **Norm of sharp texture quaternions** 78 | 79 | * number_of_quaternions = 1 80 | 81 | **For disorientation angles** 82 | 83 | * orientation_data = None 84 | 85 | **For all grains having same crystal orientation** 86 | 87 | * orientation_quaternion = np.array([1, 0, 0, 0]) 88 | 89 | **Schmid factors with random orientations** 90 | 91 | * orientation_data = None 92 | * stress_direction = np.array([1, 0, 0]) 93 | 94 | **Schmid factors with same orientations but with different stress directions** 95 | 96 | * orientation_quaternion = np.array([1, 0, 0, 0]) 97 | * stress_direction = np.array([1, -1, 0]) 98 | * stress_direction = np.array([1, 0, 0]) 99 | * stress_direction = np.array([1, 1, 0]) 100 | 101 | ### **Files used** 102 | 103 | The test case uses all modules of the package. 104 | 105 | ## **Obtained result** 106 | 107 | The obtained results are summarized below: 108 | 109 | | Characteristic feature | Obtained Results | 110 | |:-------------------------------------------------------:|:-------------------------:| 111 | | Norm of sharp texture quaternions | 1 | 112 | | Maximum value of disorientation angles | <= 62.8 | 113 | | Disorientation angles for grains with same orientations | All angles are equal to 0 | 114 | | Maximum value of Schmid factor | <= 0.5 | 115 | 116 | The following table shows the heighest schmid factor for the known stress directions: 117 | 118 | | **Stress Direction [X, Y, Z]** | **Obtained Schmid factor** | 119 | |:------------------------------:|:-------------------------:| 120 | | [1, -1, 0] | 0.408 | 121 | | [1, 0, 0] | 0.408 | 122 | | [1, 1, 0] | 0.408 | 123 | 124 | The results obtained were matching with the expected results. 125 | 126 |
-------------------------------------------------------------------------------- /optimic/test_cases/two_seed/README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **Test case 7: Two seed** 4 | 5 | ## **Aim** 6 | 7 | To test the following: 8 | 9 | 1. Volume of each grain 10 | 2. Total volume of both grains 11 | 3. Distance between grains 12 | 4. Type of grain boundary 13 | 5. Disorientation angle between grains 14 | 15 | ## **Expected result** 16 | 17 | ### **Expected results in brief:** 18 | 19 | **Volume of each grain, total volume of all grains and distance between grains** 20 | 21 | | Characteristic feature | Expected Result | Expected output | 22 | |:--------------------------:|:------------------------------------------------:|:---------------:| 23 | | Volume of each grain | 50% of total volume | 50 | 24 | | Total volume of all grains | $(size\: of \: simulation \: box)^2 * length\_z$ | 100 | 25 | | Distance between grains | 0.5 * size of simulation box | 5 | 26 | 27 | **Type of grain boundary** 28 | 29 | | **Misorientation in the form of Quaternions (real first format)** | Expected **GB type (Σ)** | 30 | |:-----------------------------------------------------------------:|:------------------------:| 31 | | (0.8166416, 0.4081033, 0.4081033, 0) | 3 | 32 | | (0.6710739, 0.6706129, 0.2235376, 0.2235376) | 5 | 33 | | (0.8017756, 0.5345322, 0.2672661, 0) | 7 | 34 | | (0.7745967, 0.5163978, 0.2581989, 0.2581989) | 15 | 35 | 36 | **Disorientation angle between grains** 37 | 38 | | **GB type** | **Misorientation in the form of Quaternions (real first format)**| Expected **Disorientation angles** | 39 | | :---: | :---: | :---: | 40 | | Σ3 | (0.8166416, 0.4081033, 0.4081033, 0) | 60° | 41 | | Σ5 | (0.6710739, 0.6706129, 0.2235376, 0.2235376) | 36.9° | 42 | | Σ7 | (0.8017756, 0.5345322, 0.2672661, 0) | 38.2° | 43 | | Σ15 | (0.7745967, 0.5163978, 0.2581989, 0.2581989) | 48.2° | 44 | 45 | ## **Command used to run the program** 46 | 47 | Please refer section 'Execute test cases' of the documentation for more details. 48 | 49 | Navigate to the **‘ppp2019_optimizedmicrostructuregeneration‘** directory using terminal. Once 50 | you are in the appropriate directory, you can execute the test case using: 51 | 52 | ```bash 53 | $ ./execute test --name two_seed 54 | ``` 55 | ### **Options:** 56 | 1. `--name` refers to the test case name (cubic_2d in this case). 57 | 2. `--f` refers to flag if opaque surface is required for VTK and OBJ files of entire configuration. 58 | 3. `--rseed` refers to the seed of Numpy random function (for eg: `--rseed 1`). 59 | 60 | Please refer section 'Basic usage' section for more details. 61 | 62 | ### **Parameters used** 63 | 64 | All the parameters used for this test case are enlisted below: 65 | 66 | * store_folder = "output_of_tests" 67 | * skewed_boundary_flag = False 68 | * face_flag = None 69 | * number_of_bins = 10 70 | * size_of_simulation_box = 10 71 | * spacing_lengths = [1, 2, 2.5, 5] 72 | * required_texture = np.array([1, 1, 1]) 73 | * rand_quat_flag = True 74 | * mesh_flag = 'TET' 75 | * global_mesh_size = 0.5 76 | * length_z = 1 77 | * dimension = 2 78 | * orientation_data = None 79 | 80 | **# Σ = 15 grain boundary orientations** 81 | 82 | * orientation_data = np.array([[1, 0, 0, 0], [0.7745967, 0.5163978, 0.2581989, 0.2581989]]) 83 | 84 | **# Σ = 5 grain boundary orientations** 85 | 86 | * orientation_data = np.array([[1, 0, 0, 0], [0.6710739, 0.6706129, 0.2235376, 0.2235376]]) 87 | 88 | **# Σ = 3 grain boundary orientations** 89 | 90 | * orientation_data = np.array([[1, 0, 0, 0], [0.8166416, 0.4081033, 0.4081033, 0]]) 91 | 92 | **# Σ = 7 grain boundary orientations** 93 | 94 | * orientation_data = np.array([[1, 0, 0, 0], [0.8017756, 0.5345322, 0.2672661, 0]]) 95 | 96 | ### **Files used** 97 | 98 | The test case uses all modules of the package. 99 | 100 | ## **Obtained result** 101 | 102 | The obtained results are summarized below: 103 | 104 | **Volume of each grain, total volume of all grains and distance between grains** 105 | 106 | | Characteristic feature | Obtained output | 107 | |:--------------------------:|:---------------:| 108 | | Volume of each grain | 50 | 109 | | Total volume of all grains | 100 | 110 | | Distance between grains | 5 | 111 | 112 | **Type of grain boundary** 113 | 114 | | **Misorientation in the form of Quaternions (real first format)** | Obtained **GB type (Σ)** | 115 | |:-----------------------------------------------------------------:|:------------------------:| 116 | | (0.8166416, 0.4081033, 0.4081033, 0) | 3 | 117 | | (0.6710739, 0.6706129, 0.2235376, 0.2235376) | 5 | 118 | | (0.8017756, 0.5345322, 0.2672661, 0) | 7 | 119 | | (0.7745967, 0.5163978, 0.2581989, 0.2581989) | 15 | 120 | 121 | **Disorientation angle between grains** 122 | 123 | | **GB type** | **Misorientation in the form of Quaternions (real first format)** | Obtained **Disorientation angles** | 124 | |:-----------:|:-----------------------------------------------------------------:|:----------------------------------:| 125 | | Σ3 | (0.8166416, 0.4081033, 0.4081033, 0) | 60° | 126 | | Σ5 | (0.6710739, 0.6706129, 0.2235376, 0.2235376) | 36.9° | 127 | | Σ7 | (0.8017756, 0.5345322, 0.2672661, 0) | 38.2° | 128 | | Σ15 | (0.7745967, 0.5163978, 0.2581989, 0.2581989) | 48.2° | 129 | 130 | 131 | The results obtained were matching with the expected results. 132 | 133 |
134 | -------------------------------------------------------------------------------- /optimic/util/user_cost_function_example2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | user_cost_function_2.py 4 | 5 | Module to demonstrate an example of user-defined cost function. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 May 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | import numpy as np 36 | import copy 37 | 38 | ## User-defined cost function designed to be used for default modules ## 39 | ## Designed only for 2D ## 40 | 41 | def mathematical_function(C, M, distArr, CritDist): 42 | """ 43 | Compute cost based on mathematical formula dependent on exponential and 44 | linear functions 45 | 46 | Parameters 47 | ---------- 48 | C: float 49 | Model constant term (used for scaling data). 50 | 51 | M: float 52 | Model constant term (used for scaling data). 53 | 54 | distArr: array 55 | Array of distances or lengths. 56 | 57 | CritDist: float 58 | Critical threshold value. 59 | 60 | Returns 61 | ------- 62 | Cost as sum of both exponential and linear terms. 63 | 64 | """ 65 | distCost=np.exp(-C * (distArr-CritDist)) + M * (distArr-CritDist) 66 | #print('Critdist: ', CritDist, distCost); exit() 67 | return np.sum(distCost) 68 | 69 | def function_formula(combined_user_data, combined_predicted_data, start_row_combined_data, data_dictionary, args): 70 | """ 71 | Computing cost function by penalizing seeds & vertices that are 72 | very close and attracts them when they are very far away. 73 | 74 | Parameters 75 | ---------- 76 | combined_user_data: array 77 | Distribution of user defined data for all characteristics. 78 | 79 | combined_predicted_data: array 80 | Distribution of predicted data for all characteristics. 81 | 82 | start_row_combined_data: list 83 | List comprising of row indexes of user and predicted data associated 84 | with each characteristic to be optimized. 85 | 86 | data_dictionary: dictionary 87 | Dictionary consisting of complete data pertaining to characteristic to 88 | be optimized. Keys used in the dictionary are integers used for 89 | identifying appropriate characteristics as below: 90 | '0': Grain sizes 91 | '1': Number of neighbors 92 | '2': Grain boundary areas 93 | '3': Junction lengths 94 | '4': Junction angles in degrees 95 | '5a': Distance between grains as 1D array 96 | '5b': Distance between grains as matrix array 97 | '6': Disorientation angles 98 | '7': Type of grain boundaries 99 | '8': Schmid factors 100 | 101 | args: list 102 | Common arguments consisting of following: 103 | 1. parameter_list 104 | 2. dimension 105 | 3. user_data 106 | 4. start_row_of_parameter 107 | 5. limit 108 | 6. number_of_bins 109 | 7. fig_animate 110 | 8. ax_animate 111 | 9. cost_function_names 112 | 10. func_name_key 113 | 11. required_texture 114 | 12. rand_quat_flag 115 | 13. stress_direction 116 | 14. orientation_data 117 | 15. skewed_boundary_flag 118 | 16. tessellation (DICTIONARY OF ALL TESSELLATION DATA) 119 | 120 | Returns 121 | ------- 122 | Sum of cost value obtained by considering both distance between grains 123 | and edge length. 124 | 125 | """ 126 | C = 0.6 127 | M = 0.6 128 | 129 | #args_list = [parameter_list, dimension, user_data, start_row_of_parameter, limit, number_of_bins, fig_animate, ax_animate, cost_function_names, func_name_key, required_texture, rand_quat_flag, stress_direction, orientation_data, skewed_boundary_flag, tessellation] 130 | limit = args[4] 131 | tessellation = copy.deepcopy(args[15]) 132 | 133 | CritDist_dist = 0.1*min(args[4][:args[1]]) 134 | all_distances_array = np.array(data_dictionary['5a']) 135 | 136 | cost_value_dist = mathematical_function(C, M, all_distances_array, CritDist_dist) 137 | 138 | CritDist_edge = 0.05*min(args[4][:args[1]]) 139 | all_ridge_lengths = np.array([v[3]/limit[2] for v in data_dictionary['2']]) #######REMEMBER####### 140 | cost_value_edge = mathematical_function(C, M, all_ridge_lengths, CritDist_edge) 141 | 142 | return (cost_value_dist + cost_value_edge) -------------------------------------------------------------------------------- /optimic/src/create_tessellations_non_default.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | create_tessellations_non_default.py 4 | 5 | Module to perform voronoi tessellations using 'Scipy.spatial' package 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | from scipy.spatial import Voronoi 35 | import copy 36 | 37 | from optimic.src.main_import_statements import * 38 | from optimic.src.set_logger import set_logger 39 | 40 | name_str = __name__ 41 | 42 | def replicateForPeriodicity(seedPoints, boxLenArr): 43 | """ 44 | Function to replicate a given set of points (both -ve and +ve) to obtain a periodic structure 45 | ###Currently for ndim=2 46 | """ 47 | boxLenX=boxLenArr[0] 48 | boxLenY=boxLenArr[1] 49 | seedPoints=np.asarray(seedPoints) 50 | seedPointsPeriodic=copy.deepcopy(seedPoints.tolist()) 51 | for ix in [-1,0,1]: 52 | for jy in [-1,0,1]: 53 | if (not (ix==0 and jy==0)): 54 | for pt in seedPoints: 55 | x = pt[0] + ix*boxLenX 56 | y = pt[1] + jy*boxLenY 57 | seedPointsPeriodic.append([x,y]) 58 | 59 | return np.array(seedPointsPeriodic) 60 | 61 | def create_tessellations(seed_array, limit, log_level): #x are seed coordinates, y are limits 62 | """ 63 | Create tessellations with Periodicity to be True by default. This function 64 | is a non default module to be used to ensure that the entire project is 65 | modular. 66 | 67 | Parameters 68 | ---------- 69 | seed_array: array 70 | Array of seed coordinates in 3D. 71 | 72 | limit: array 73 | Size of simulation box along X, Y & Z direction. 74 | 75 | log_level: string 76 | Logger level to be used. 77 | 78 | Returns 79 | ------- 80 | Dictionary of tessellations data with following keys: 81 | 1. number_of_grains 82 | 2. number_of_faces_list 83 | 3. vertices_list 84 | 4. face_vertices_list 85 | 5. centroid_list 86 | 6. volume_list 87 | 7. normals_list 88 | 8. neighbors_list 89 | 9. face_area_list 90 | 10. number_of_edges_list 91 | 11. ScipyVoroVertices 92 | 12. ScipyRidgeDictList 93 | 13. ScipyPoints 94 | """ 95 | log = set_logger(__name__, 'log_data.log', log_level) 96 | log.debug('Tessellations are to be created with limits as ' + str(limit) + ' and seed array as:\n' + str(seed_array)) 97 | 98 | local_tessellation = Container(seed_array, limits=limit, periodic = True) 99 | 100 | log.info('Tessellations were created successfully.') 101 | 102 | number_of_grains = len(local_tessellation) 103 | number_of_faces_list = [v.number_of_faces() for v in local_tessellation] 104 | vertices_list = [v.vertices() for v in local_tessellation] 105 | face_vertices_list = [v.face_vertices() for v in local_tessellation] 106 | centroid_list = [v.centroid() for v in local_tessellation] 107 | volume_list = [v.volume() for v in local_tessellation] 108 | normals_list = [v.normals() for v in local_tessellation] 109 | neighbors_list = [v.neighbors() for v in local_tessellation] 110 | face_area_list = [v.face_areas() for v in local_tessellation] 111 | number_of_edges_list = [v.number_of_edges() for v in local_tessellation] 112 | 113 | log.info('All required properties of created tessellations are stored in the dictionary successfully.') 114 | 115 | ## Creating tessellations using Scipy Voronoi 116 | scipy_seed_array = seed_array[: , :2] 117 | periodic_seeds = replicateForPeriodicity(scipy_seed_array, limit) 118 | local_tessellation = Voronoi(periodic_seeds) 119 | 120 | ## Adding data from Tess library not available from Scipy Voronoi to tessellation dictionary 121 | tessellation = {} 122 | tessellation['number_of_grains'] = len(scipy_seed_array) 123 | tessellation['number_of_faces_list'] = number_of_faces_list 124 | tessellation['vertices_list'] = vertices_list 125 | tessellation['face_vertices_list'] = face_vertices_list 126 | tessellation['centroid_list'] = centroid_list 127 | tessellation['volume_list'] = volume_list 128 | tessellation['normals_list'] = normals_list 129 | tessellation['neighbors_list'] = neighbors_list 130 | tessellation['face_area_list'] = face_area_list 131 | tessellation['number_of_edges_list'] = number_of_edges_list 132 | 133 | ## Adding data available from Scipy Voronoi to tessellation dictionary 134 | tessellation['ScipyVoroVertices'] = local_tessellation.vertices 135 | tessellation['ScipyRidgeDictList'] = list(local_tessellation.ridge_dict.items()) 136 | tessellation['ScipyPoints']=local_tessellation.points 137 | 138 | return tessellation # returns list of cells as class instances 139 | -------------------------------------------------------------------------------- /optimic/test_cases/hcp_3d/hcp_3d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | hcp_3d_testcase.py 4 | 5 | Module to test some features of program for HCP 3D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 15 October 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def hcp_3d_testcase(tessellation, dimension, size_of_simulation_box, \ 41 | spacing_length, grain_size_distributions, number_of_neighbor, \ 42 | grain_boundary_area_distribution, junction_lengths, \ 43 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 44 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 45 | """ 46 | Execute all assert statements related to hcp_3d_testcase. 47 | 48 | Parameters 49 | ---------- 50 | tessellation: dictionary 51 | Dictionary of tessellations data with following keys: 52 | 1. number_of_grains 53 | 2. number_of_faces_list 54 | 3. vertices_list 55 | 4. face_vertices_list 56 | 5. centroid_list 57 | 6. volume_list 58 | 7. normals_list 59 | 8. neighbors_list 60 | 9. face_area_list 61 | 10. number_of_edges_list 62 | 63 | dimension: integer 64 | Dimension of study (2 or 3) 65 | 66 | size_of_simulation_box: array of length 3 67 | Size of simulation box (array of length along X, Y, Z directions) 68 | 69 | spacing_length: float 70 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 71 | directions in Quasi-2D case. Also the spacing_length must be a perfect 72 | divisor of size of simulation box along all three directions. 73 | 74 | grain_size_distribution: 2D array 75 | An array of all the grain sizes in terms of radius. The 76 | first column is the grain number and second column consists of grain 77 | sizes. 78 | 79 | number_of_neighbor: 2D array 80 | An array comprising of data related to the number of 81 | neighbors of each grains. Column names are: Grain number, number of 82 | neighbors, grain indexes of neighbors. 83 | 84 | grain_boundary_area_distribution_ 2D array 85 | An array of consisting of columns Sr. No., Grain 1, 86 | Grain 2 and grain boundary area. 87 | 88 | junction_lengths: List of lists 89 | List of lists consisting of column names: Sr. no., Junction type, 90 | Junction lengths, grains with this junction. 91 | 92 | junction_angles_degrees: List of lists 93 | List of lists consisting of column names: Sr. No., Junction Type, 94 | 1st Junction angle, Grain containing the 1st junction angle, 95 | 2nd Junction angle, so on... 96 | 97 | distance_btw_grain_array: 2D array 98 | Symmetric array with rows and columns represented by grain numbers in 99 | ascending order and each element of the array representing distance 100 | between respective grain numbers. 101 | 102 | distance_btw_grain_1d: 1D array 103 | 1D array of distances between grains 104 | 105 | disorientation_angle: 2D array 106 | An array consisting of columns grain 1, grain 2, disorientation 107 | angle, disorientation axis. 108 | 109 | schmid_factors: 2D array 110 | An array consisting of Schmid Factor related data with column names as 111 | Grain no., Schmid factor, Slip plane and direction (Slip System). 112 | 113 | type_of_grain_boundaries: 2D array 114 | An array with the column names as grain 1, grain 2, rotation angle, 115 | rotation axis, type of csl (0 indicates normal grain boundary). 116 | 117 | log_level: string 118 | Logger level to be used. 119 | 120 | Returns 121 | ------- 122 | Function returns nothing. 123 | 124 | """ 125 | 126 | 127 | log = set_logger(name_str, 'log_data.log', log_level) 128 | try: 129 | ## Number of faces 130 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 131 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]), 14) 132 | 133 | ## Grain SIze distribution 134 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 135 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(0.9847*spacing_length, decimals=2)]) # The grain sizes should be the same 136 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.cbrt((size_of_simulation_box**3 * 6)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 137 | 138 | ## Number of neighbors 139 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 140 | assert np.all([np.isclose(num[2], 10) for num in number_of_neighbor]) # The no. of neighbors should be the same 141 | except AssertionError: 142 | log.exception('hcp_3d_testcase failed !!') 143 | 144 | log.info('hcp_3d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/bcc_3d/bcc_3d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | bcc_3d_testcase.py 4 | 5 | Module to test some features of program for BCC 3D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def bcc_3d_testcase(tessellation, dimension, size_of_simulation_box, \ 41 | spacing_length, grain_size_distributions, number_of_neighbor, \ 42 | grain_boundary_area_distribution, junction_lengths, \ 43 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 44 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 45 | """ 46 | Execute all assert statements related to bcc_3d_testcase. 47 | 48 | Parameters 49 | ---------- 50 | tessellation: dictionary 51 | Dictionary of tessellations data with following keys: 52 | 1. number_of_grains 53 | 2. number_of_faces_list 54 | 3. vertices_list 55 | 4. face_vertices_list 56 | 5. centroid_list 57 | 6. volume_list 58 | 7. normals_list 59 | 8. neighbors_list 60 | 9. face_area_list 61 | 10. number_of_edges_list 62 | 63 | dimension: integer 64 | Dimension of study (2 or 3) 65 | 66 | size_of_simulation_box: array of length 3 67 | Size of simulation box (array of length along X, Y, Z directions) 68 | 69 | spacing_length: float 70 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 71 | directions in Quasi-2D case. Also the spacing_length must be a perfect 72 | divisor of size of simulation box along all three directions. 73 | 74 | grain_size_distribution: 2D array 75 | An array of all the grain sizes in terms of radius. The 76 | first column is the grain number and second column consists of grain 77 | sizes. 78 | 79 | number_of_neighbor: 2D array 80 | An array comprising of data related to the number of 81 | neighbors of each grains. Column names are: Grain number, number of 82 | neighbors, grain indexes of neighbors. 83 | 84 | grain_boundary_area_distribution_ 2D array 85 | An array of consisting of columns Sr. No., Grain 1, 86 | Grain 2 and grain boundary area. 87 | 88 | junction_lengths: List of lists 89 | List of lists consisting of column names: Sr. no., Junction type, 90 | Junction lengths, grains with this junction. 91 | 92 | junction_angles_degrees: List of lists 93 | List of lists consisting of column names: Sr. No., Junction Type, 94 | 1st Junction angle, Grain containing the 1st junction angle, 95 | 2nd Junction angle, so on... 96 | 97 | distance_btw_grain_array: 2D array 98 | Symmetric array with rows and columns represented by grain numbers in 99 | ascending order and each element of the array representing distance 100 | between respective grain numbers. 101 | 102 | distance_btw_grain_1d: 1D array 103 | 1D array of distances between grains 104 | 105 | disorientation_angle: 2D array 106 | An array consisting of columns grain 1, grain 2, disorientation 107 | angle, disorientation axis. 108 | 109 | schmid_factors: 2D array 110 | An array consisting of Schmid Factor related data with column names as 111 | Grain no., Schmid factor, Slip plane and direction (Slip System). 112 | 113 | type_of_grain_boundaries: 2D array 114 | An array with the column names as grain 1, grain 2, rotation angle, 115 | rotation axis, type of csl (0 indicates normal grain boundary). 116 | 117 | log_level: string 118 | Logger level to be used. 119 | 120 | Returns 121 | ------- 122 | Function returns nothing. 123 | 124 | """ 125 | 126 | 127 | log = set_logger(name_str, 'log_data.log', log_level) 128 | try: 129 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 130 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]), 14) 131 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 132 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(0.9847*spacing_length, decimals=2)]) # The grain sizes should be the same 133 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.cbrt((size_of_simulation_box**3 * 6)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 134 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 135 | assert np.all([np.isclose(num[2], 14) for num in number_of_neighbor]) # The no. of neighbors should be the same 136 | assert np.all([np.isclose(lengths[2], junction_lengths[0][2]) for lengths in junction_lengths]) # The junctions length should be the same 137 | assert np.all([np.isclose(lengths[2], 0.3536*spacing_length, atol=1e-2) for lengths in junction_lengths]) # The junctions length should be the same 138 | except AssertionError: 139 | log.exception('bcc_3d_testcase failed !!') 140 | 141 | log.info('bcc_3d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/fcc_3d/fcc_3d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | fcc_3d_testcase.py 4 | 5 | Module to test some features of program for FCC 3D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def fcc_3d_testcase(tessellation, dimension, size_of_simulation_box, \ 41 | spacing_length, grain_size_distributions, number_of_neighbor, \ 42 | grain_boundary_area_distribution, junction_lengths, \ 43 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 44 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 45 | """ 46 | Execute all assert statements related to fcc_3d_testcase. 47 | 48 | Parameters 49 | ---------- 50 | tessellation: dictionary 51 | Dictionary of tessellations data with following keys: 52 | 1. number_of_grains 53 | 2. number_of_faces_list 54 | 3. vertices_list 55 | 4. face_vertices_list 56 | 5. centroid_list 57 | 6. volume_list 58 | 7. normals_list 59 | 8. neighbors_list 60 | 9. face_area_list 61 | 10. number_of_edges_list 62 | 63 | dimension: integer 64 | Dimension of study (2 or 3) 65 | 66 | size_of_simulation_box: array of length 3 67 | Size of simulation box (array of length along X, Y, Z directions) 68 | 69 | spacing_length: float 70 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 71 | directions in Quasi-2D case. Also the spacing_length must be a perfect 72 | divisor of size of simulation box along all three directions. 73 | 74 | grain_size_distribution: 2D array 75 | An array of all the grain sizes in terms of radius. The 76 | first column is the grain number and second column consists of grain 77 | sizes. 78 | 79 | number_of_neighbor: 2D array 80 | An array comprising of data related to the number of 81 | neighbors of each grains. Column names are: Grain number, number of 82 | neighbors, grain indexes of neighbors. 83 | 84 | grain_boundary_area_distribution_ 2D array 85 | An array of consisting of columns Sr. No., Grain 1, 86 | Grain 2 and grain boundary area. 87 | 88 | junction_lengths: List of lists 89 | List of lists consisting of column names: Sr. no., Junction type, 90 | Junction lengths, grains with this junction. 91 | 92 | junction_angles_degrees: List of lists 93 | List of lists consisting of column names: Sr. No., Junction Type, 94 | 1st Junction angle, Grain containing the 1st junction angle, 95 | 2nd Junction angle, so on... 96 | 97 | distance_btw_grain_array: 2D array 98 | Symmetric array with rows and columns represented by grain numbers in 99 | ascending order and each element of the array representing distance 100 | between respective grain numbers. 101 | 102 | distance_btw_grain_1d: 1D array 103 | 1D array of distances between grains 104 | 105 | disorientation_angle: 2D array 106 | An array consisting of columns grain 1, grain 2, disorientation 107 | angle, disorientation axis. 108 | 109 | schmid_factors: 2D array 110 | An array consisting of Schmid Factor related data with column names as 111 | Grain no., Schmid factor, Slip plane and direction (Slip System). 112 | 113 | type_of_grain_boundaries: 2D array 114 | An array with the column names as grain 1, grain 2, rotation angle, 115 | rotation axis, type of csl (0 indicates normal grain boundary). 116 | 117 | log_level: string 118 | Logger level to be used. 119 | 120 | Returns 121 | ------- 122 | Function returns nothing. 123 | 124 | """ 125 | 126 | log = set_logger(name_str, 'log_data.log', log_level) 127 | try: 128 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 129 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]), 12) 130 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 131 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(0.7816*spacing_length, decimals=2)]) # The grain sizes should be the same 132 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.cbrt((size_of_simulation_box**3 * 6)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 133 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 134 | assert np.all([np.isclose(num[2], 12) for num in number_of_neighbor]) # The no. of neighbors should be the same 135 | assert np.all([np.isclose(area[3], grain_boundary_area_distribution[0][3]) for area in grain_boundary_area_distribution]) # The GB areas should be the same 136 | assert np.all([np.isclose(area[3], 0.1768*(spacing_length**2), atol=1e-2) for area in grain_boundary_area_distribution]) # The GB areas should be the same 137 | assert np.all([np.isclose(length[2], junction_lengths[0][2]) for length in junction_lengths]) # The junctions length should be the same 138 | assert np.all([np.isclose(length[2], 0.4330*spacing_length, atol=1e-2) for length in junction_lengths]) # The junctions length should be the same 139 | assert np.all(np.array([np.allclose(angles[2::2], 120.0) for angles in junction_angles_degrees])) # All angles should be the same 140 | except AssertionError: 141 | log.exception('fcc_3d_testcase failed !!') 142 | 143 | log.info('fcc_3d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/cubic_3d/cubic_3d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | cubic_3d_testcase.py 4 | 5 | Module to test some features of program for CUBIC 3D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def cubic_3d_testcase(tessellation, dimension, size_of_simulation_box, \ 41 | spacing_length, grain_size_distributions, number_of_neighbor, \ 42 | grain_boundary_area_distribution, junction_lengths, \ 43 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 44 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 45 | """ 46 | Execute all assert statements related to cubic_3d_testcase. 47 | 48 | Parameters 49 | ---------- 50 | tessellation: dictionary 51 | Dictionary of tessellations data with following keys: 52 | 1. number_of_grains 53 | 2. number_of_faces_list 54 | 3. vertices_list 55 | 4. face_vertices_list 56 | 5. centroid_list 57 | 6. volume_list 58 | 7. normals_list 59 | 8. neighbors_list 60 | 9. face_area_list 61 | 10. number_of_edges_list 62 | 63 | dimension: integer 64 | Dimension of study (2 or 3) 65 | 66 | size_of_simulation_box: array of length 3 67 | Size of simulation box (array of length along X, Y, Z directions) 68 | 69 | spacing_length: float 70 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 71 | directions in Quasi-2D case. Also the spacing_length must be a perfect 72 | divisor of size of simulation box along all three directions. 73 | 74 | grain_size_distribution: 2D array 75 | An array of all the grain sizes in terms of radius. The 76 | first column is the grain number and second column consists of grain 77 | sizes. 78 | 79 | number_of_neighbor: 2D array 80 | An array comprising of data related to the number of 81 | neighbors of each grains. Column names are: Grain number, number of 82 | neighbors, grain indexes of neighbors. 83 | 84 | grain_boundary_area_distribution_ 2D array 85 | An array of consisting of columns Sr. No., Grain 1, 86 | Grain 2 and grain boundary area. 87 | 88 | junction_lengths: List of lists 89 | List of lists consisting of column names: Sr. no., Junction type, 90 | Junction lengths, grains with this junction. 91 | 92 | junction_angles_degrees: List of lists 93 | List of lists consisting of column names: Sr. No., Junction Type, 94 | 1st Junction angle, Grain containing the 1st junction angle, 95 | 2nd Junction angle, so on... 96 | 97 | distance_btw_grain_array: 2D array 98 | Symmetric array with rows and columns represented by grain numbers in 99 | ascending order and each element of the array representing distance 100 | between respective grain numbers. 101 | 102 | distance_btw_grain_1d: 1D array 103 | 1D array of distances between grains 104 | 105 | disorientation_angle: 2D array 106 | An array consisting of columns grain 1, grain 2, disorientation 107 | angle, disorientation axis. 108 | 109 | schmid_factors: 2D array 110 | An array consisting of Schmid Factor related data with column names as 111 | Grain no., Schmid factor, Slip plane and direction (Slip System). 112 | 113 | type_of_grain_boundaries: 2D array 114 | An array with the column names as grain 1, grain 2, rotation angle, 115 | rotation axis, type of csl (0 indicates normal grain boundary). 116 | 117 | log_level: string 118 | Logger level to be used. 119 | 120 | Returns 121 | ------- 122 | Function returns nothing. 123 | 124 | """ 125 | 126 | log = set_logger(name_str, 'log_data.log', log_level) 127 | try: 128 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 129 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]), 6) 130 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 131 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(1.2407*spacing_length, decimals=2)]) # The grain sizes should be the same 132 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.cbrt((size_of_simulation_box**3 * 6)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 133 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 134 | assert np.all([np.isclose(num[2], 6) for num in number_of_neighbor]) # The no. of neighbors should be the same 135 | assert np.all([np.isclose(area[3], grain_boundary_area_distribution[0][3]) for area in grain_boundary_area_distribution]) # The GB areas should be the same 136 | assert np.all([np.around(area[3], decimals=2) == np.around(spacing_length**2, decimals=2) for area in grain_boundary_area_distribution]) # The GB areas should be the same 137 | assert np.all([np.isclose(length[2], junction_lengths[0][2]) for length in junction_lengths]) # The junctions length should be the same 138 | assert np.all([np.around(length[2], decimals=2) == np.around(spacing_length, decimals=2) for length in junction_lengths]) # The junctions length should be the same 139 | assert np.all(np.concatenate(np.array([np.equal(angles[2::2], 90.0) for angles in junction_angles_degrees])).flatten()) # All angles should be the same 140 | except AssertionError: 141 | log.exception('cubic_3d_testcase failed !!') 142 | 143 | log.info('cubic_3d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/hcp_2d/hcp_2d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | hcp_2d_testcase.py 4 | 5 | Module to test some features of program for HCP 2D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | 41 | def hcp_2d_testcase(tessellation, dimension, size_of_simulation_box, \ 42 | spacing_length, length_z, grain_size_distributions, number_of_neighbor, \ 43 | grain_boundary_area_distribution, junction_lengths, \ 44 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 45 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 46 | """ 47 | Execute all assert statements related to hcp_2d_testcase. 48 | 49 | Parameters 50 | ---------- 51 | tessellation: dictionary 52 | Dictionary of tessellations data with following keys: 53 | 1. number_of_grains 54 | 2. number_of_faces_list 55 | 3. vertices_list 56 | 4. face_vertices_list 57 | 5. centroid_list 58 | 6. volume_list 59 | 7. normals_list 60 | 8. neighbors_list 61 | 9. face_area_list 62 | 10. number_of_edges_list 63 | 64 | dimension: integer 65 | Dimension of study (2 or 3) 66 | 67 | size_of_simulation_box: array of length 3 68 | Size of simulation box (array of length along X, Y, Z directions) 69 | 70 | spacing_length: float 71 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 72 | directions in Quasi-2D case. Also the spacing_length must be a perfect 73 | divisor of size of simulation box along all three directions. 74 | 75 | length_z: float 76 | Size of simulation box along Z axis. 77 | 78 | grain_size_distribution: 2D array 79 | An array of all the grain sizes in terms of radius. The 80 | first column is the grain number and second column consists of grain 81 | sizes. 82 | 83 | number_of_neighbor: 2D array 84 | An array comprising of data related to the number of 85 | neighbors of each grains. Column names are: Grain number, number of 86 | neighbors, grain indexes of neighbors. 87 | 88 | grain_boundary_area_distribution_ 2D array 89 | An array of consisting of columns Sr. No., Grain 1, 90 | Grain 2 and grain boundary area. 91 | 92 | junction_lengths: List of lists 93 | List of lists consisting of column names: Sr. no., Junction type, 94 | Junction lengths, grains with this junction. 95 | 96 | junction_angles_degrees: List of lists 97 | List of lists consisting of column names: Sr. No., Junction Type, 98 | 1st Junction angle, Grain containing the 1st junction angle, 99 | 2nd Junction angle, so on... 100 | 101 | distance_btw_grain_array: 2D array 102 | Symmetric array with rows and columns represented by grain numbers in 103 | ascending order and each element of the array representing distance 104 | between respective grain numbers. 105 | 106 | distance_btw_grain_1d: 1D array 107 | 1D array of distances between grains 108 | 109 | disorientation_angle: 2D array 110 | An array consisting of columns grain 1, grain 2, disorientation 111 | angle, disorientation axis. 112 | 113 | schmid_factors: 2D array 114 | An array consisting of Schmid Factor related data with column names as 115 | Grain no., Schmid factor, Slip plane and direction (Slip System). 116 | 117 | type_of_grain_boundaries: 2D array 118 | An array with the column names as grain 1, grain 2, rotation angle, 119 | rotation axis, type of csl (0 indicates normal grain boundary). 120 | 121 | log_level: string 122 | Logger level to be used. 123 | 124 | Returns 125 | ------- 126 | Function returns nothing. 127 | 128 | """ 129 | 130 | log = set_logger(name_str, 'log_data.log', log_level) 131 | try: 132 | ## Number of faces 133 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 134 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]) - 2, 6) ## ignoring surfaces with surface normals along z axis. REMEMBER !!!!!! 135 | 136 | ## Grain size distribution 137 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 138 | assert np.allclose(grain_size_distributions[:, 1], (1.0501)*spacing_length, atol=1e-4) 139 | 140 | ## Number of neighbors 141 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 142 | assert np.all([np.isclose(num[2], 6) for num in number_of_neighbor]) 143 | 144 | ## GB area 145 | assert np.all([np.isclose(area[3], grain_boundary_area_distribution[0][3]) for area in grain_boundary_area_distribution]) 146 | assert np.all([np.isclose(area[3], 0.57735*spacing_length*length_z, atol=1e-2) for area in grain_boundary_area_distribution]) 147 | 148 | ## Junction length 149 | assert np.all([((np.around(length[2], decimals=2) == np.around(0.57735 * spacing_length, decimals=2)) or (length[2] == length_z)) for length in junction_lengths]) 150 | 151 | ## Type of junction 152 | if spacing_length == 5.0: 153 | types_of_junction_list = [length[1] for length in junction_lengths] 154 | assert (types_of_junction_list.count(1) == 14) # Total 14 junctions belong to type 1 junction 155 | assert (types_of_junction_list.count(2) == 8) # total 8 junctions belong to type 2 junction 156 | assert (types_of_junction_list.count(3) == 6) # total 6 junctions belong to triple junctions 157 | 158 | ## Junction angles 159 | all_junction_angles = (np.concatenate(np.array([angles[2::2] for angles in junction_angles_degrees]))).flatten() 160 | assert np.all([np.isclose(angle, 120.0) for angle in np.around(all_junction_angles, decimals=3)]) 161 | except AssertionError: 162 | log.exception('hcp_2d_testcase failed !!') 163 | 164 | log.info('hcp_2d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/fcc_2d/fcc_2d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | fcc_2d_testcase.py 4 | 5 | Module to test some features of program for FCC 2D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | 41 | def fcc_2d_testcase(tessellation, dimension, size_of_simulation_box, \ 42 | spacing_length, length_z, grain_size_distributions, number_of_neighbor, \ 43 | grain_boundary_area_distribution, junction_lengths, \ 44 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 45 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 46 | """ 47 | Execute all assert statements related to fcc_2d_testcase. 48 | 49 | Parameters 50 | ---------- 51 | tessellation: dictionary 52 | Dictionary of tessellations data with following keys: 53 | 1. number_of_grains 54 | 2. number_of_faces_list 55 | 3. vertices_list 56 | 4. face_vertices_list 57 | 5. centroid_list 58 | 6. volume_list 59 | 7. normals_list 60 | 8. neighbors_list 61 | 9. face_area_list 62 | 10. number_of_edges_list 63 | 64 | dimension: integer 65 | Dimension of study (2 or 3) 66 | 67 | size_of_simulation_box: array of length 3 68 | Size of simulation box (array of length along X, Y, Z directions) 69 | 70 | spacing_length: float 71 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 72 | directions in Quasi-2D case. Also the spacing_length must be a perfect 73 | divisor of size of simulation box along all three directions. 74 | 75 | length_z: float 76 | Size of simulation box along Z axis. 77 | 78 | grain_size_distribution: 2D array 79 | An array of all the grain sizes in terms of radius. The 80 | first column is the grain number and second column consists of grain 81 | sizes. 82 | 83 | number_of_neighbor: 2D array 84 | An array comprising of data related to the number of 85 | neighbors of each grains. Column names are: Grain number, number of 86 | neighbors, grain indexes of neighbors. 87 | 88 | grain_boundary_area_distribution_ 2D array 89 | An array of consisting of columns Sr. No., Grain 1, 90 | Grain 2 and grain boundary area. 91 | 92 | junction_lengths: List of lists 93 | List of lists consisting of column names: Sr. no., Junction type, 94 | Junction lengths, grains with this junction. 95 | 96 | junction_angles_degrees: List of lists 97 | List of lists consisting of column names: Sr. No., Junction Type, 98 | 1st Junction angle, Grain containing the 1st junction angle, 99 | 2nd Junction angle, so on... 100 | 101 | distance_btw_grain_array: 2D array 102 | Symmetric array with rows and columns represented by grain numbers in 103 | ascending order and each element of the array representing distance 104 | between respective grain numbers. 105 | 106 | distance_btw_grain_1d: 1D array 107 | 1D array of distances between grains 108 | 109 | disorientation_angle: 2D array 110 | An array consisting of columns grain 1, grain 2, disorientation 111 | angle, disorientation axis. 112 | 113 | schmid_factors: 2D array 114 | An array consisting of Schmid Factor related data with column names as 115 | Grain no., Schmid factor, Slip plane and direction (Slip System). 116 | 117 | type_of_grain_boundaries: 2D array 118 | An array with the column names as grain 1, grain 2, rotation angle, 119 | rotation axis, type of csl (0 indicates normal grain boundary). 120 | 121 | log_level: string 122 | Logger level to be used. 123 | 124 | Returns 125 | ------- 126 | Function returns nothing. 127 | 128 | """ 129 | 130 | log = set_logger(name_str, 'log_data.log', log_level) 131 | try: 132 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 133 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]) - 2, 4) ## ignoring surfaces with surface normals along z axis. REMEMBER !!!!!! 134 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 135 | assert np.allclose(grain_size_distributions[:, 1], 0.7979*spacing_length, atol=1e-4) 136 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.sqrt((size_of_simulation_box**2 * 4)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 137 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 138 | assert np.all([np.isclose(num[2], 4) for num in number_of_neighbor]) 139 | assert np.all([np.isclose(area[3], grain_boundary_area_distribution[0][3]) for area in grain_boundary_area_distribution]) 140 | assert np.all([np.isclose(area[3], 0.7071*spacing_length*length_z, atol=1e-2) for area in grain_boundary_area_distribution]) 141 | 142 | ## Junction length 143 | assert np.all([(length[2] == length_z) for length in junction_lengths]) 144 | 145 | ## Type of junction 146 | if spacing_length == 5.0: 147 | types_of_junction_list = [length[1] for length in junction_lengths] 148 | assert (types_of_junction_list.count(1) == 8) # Total 8 junctions belong to type 1 junction 149 | assert (types_of_junction_list.count(2) == 2) # total 2 junctions belong to type 2 junction 150 | assert (types_of_junction_list.count(3) == 4) # total 6 junctions belong to triple junctions 151 | assert (types_of_junction_list.count(4) == 2) # total 6 junctions belong to quadruple junctions 152 | 153 | assert np.all(np.concatenate(np.array([np.equal(angles[2::2], 90.0) for angles in junction_angles_degrees])).flatten()) # All angles should be the same 154 | except AssertionError: 155 | log.exception('fcc_2d_testcase failed !!') 156 | 157 | log.info('fcc_2d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/cubic_2d/cubic_2d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | cubic_2d_testcase.py 4 | 5 | Module to test some features of program for CUBIC 2D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def cubic_2d_testcase(tessellation, dimension, size_of_simulation_box, \ 41 | spacing_length, length_z, grain_size_distributions, number_of_neighbor, \ 42 | grain_boundary_area_distribution, junction_lengths, \ 43 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 44 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 45 | """ 46 | Execute all assert statements related to cubic_2d_testcase. 47 | 48 | Parameters 49 | ---------- 50 | tessellation: dictionary 51 | Dictionary of tessellations data with following keys: 52 | 1. number_of_grains 53 | 2. number_of_faces_list 54 | 3. vertices_list 55 | 4. face_vertices_list 56 | 5. centroid_list 57 | 6. volume_list 58 | 7. normals_list 59 | 8. neighbors_list 60 | 9. face_area_list 61 | 10. number_of_edges_list 62 | 63 | dimension: integer 64 | Dimension of study (2 or 3) 65 | 66 | size_of_simulation_box: array of length 3 67 | Size of simulation box (array of length along X, Y, Z directions) 68 | 69 | spacing_length: float 70 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 71 | directions in Quasi-2D case. Also the spacing_length must be a perfect 72 | divisor of size of simulation box along all three directions. 73 | 74 | length_z: float 75 | Size of simulation box along Z axis. 76 | 77 | grain_size_distribution: 2D array 78 | An array of all the grain sizes in terms of radius. The 79 | first column is the grain number and second column consists of grain 80 | sizes. 81 | 82 | number_of_neighbor: 2D array 83 | An array comprising of data related to the number of 84 | neighbors of each grains. Column names are: Grain number, number of 85 | neighbors, grain indexes of neighbors. 86 | 87 | grain_boundary_area_distribution_ 2D array 88 | An array of consisting of columns Sr. No., Grain 1, 89 | Grain 2 and grain boundary area. 90 | 91 | junction_lengths: List of lists 92 | List of lists consisting of column names: Sr. no., Junction type, 93 | Junction lengths, grains with this junction. 94 | 95 | junction_angles_degrees: List of lists 96 | List of lists consisting of column names: Sr. No., Junction Type, 97 | 1st Junction angle, Grain containing the 1st junction angle, 98 | 2nd Junction angle, so on... 99 | 100 | distance_btw_grain_array: 2D array 101 | Symmetric array with rows and columns represented by grain numbers in 102 | ascending order and each element of the array representing distance 103 | between respective grain numbers. 104 | 105 | distance_btw_grain_1d: 1D array 106 | 1D array of distances between grains 107 | 108 | disorientation_angle: 2D array 109 | An array consisting of columns grain 1, grain 2, disorientation 110 | angle, disorientation axis. 111 | 112 | schmid_factors: 2D array 113 | An array consisting of Schmid Factor related data with column names as 114 | Grain no., Schmid factor, Slip plane and direction (Slip System). 115 | 116 | type_of_grain_boundaries: 2D array 117 | An array with the column names as grain 1, grain 2, rotation angle, 118 | rotation axis, type of csl (0 indicates normal grain boundary). 119 | 120 | log_level: string 121 | Logger level to be used. 122 | 123 | Returns 124 | ------- 125 | Function returns nothing. 126 | """ 127 | 128 | 129 | 130 | log = set_logger(name_str, 'log_data.log', log_level) 131 | try: 132 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 133 | assert np.isclose(copy.deepcopy(tessellation['number_of_faces_list'][v]) - dimension, 4) # ignoring surfaces with surface normals along z axis. REMEMBER !!!!!! 134 | assert np.all([grain_size_distributions[:, 1] == grain_size_distributions[0, 1]]) # The grain sizes should be the same 135 | assert np.allclose(grain_size_distributions[:, 1], 1.1284*spacing_length, atol=1e-2) # Please refer documentation for details regarding 1.1284 136 | assert np.all([np.around(grain_size_distributions[:, 1], decimals=2) == np.around(np.sqrt((size_of_simulation_box**2 * 4)/(np.pi * copy.deepcopy(tessellation['number_of_grains'])) ), decimals=2)]) # The grain sizes should be the same 137 | assert np.all([np.isclose(num[2], number_of_neighbor[0][2]) for num in number_of_neighbor]) # The no. of neighbors should be the same 138 | assert np.all([np.isclose(num[2], 4) for num in number_of_neighbor]) 139 | assert np.all([np.isclose(area[3], grain_boundary_area_distribution[0][3]) for area in grain_boundary_area_distribution]) 140 | assert np.all([np.isclose(area[3], length_z*spacing_length) for area in grain_boundary_area_distribution]) 141 | #assert np.all([length[2] == junction_lengths[0][2] for length in junction_lengths]) # The junctions length should be the same 142 | 143 | ## Junction length 144 | assert np.all([(length[2] == length_z) for length in junction_lengths]) 145 | 146 | ## Type of junction 147 | if spacing_length == 5.0: 148 | types_of_junction_list = [length[1] for length in junction_lengths] 149 | assert (types_of_junction_list.count(1) == 4) # Total 4 junctions belong to type 1 junction 150 | assert (types_of_junction_list.count(2) == 4) # total 4 junctions belong to type 2 junction 151 | assert (types_of_junction_list.count(4) == 1) # total 1 junctions belong to quadruple junctions 152 | 153 | assert np.all(np.concatenate(np.array([np.equal(angles[2::2], 90.0) for angles in junction_angles_degrees])).flatten()) # All angles should be the same 154 | except AssertionError: 155 | log.exception('cubic_2d_testcase failed !!') 156 | 157 | log.info('cubic_2d_testcase passed !!') -------------------------------------------------------------------------------- /optimic/test_cases/random_3d/random_3d_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | random_3d_testcase.py 4 | 5 | Module to test some features of program for RANDOM 3D type spacing. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | from optimic.src.textural_characteristics import sharp_texture_quaternions 41 | from optimic.src.textural_characteristics import random_quaternions_generator 42 | from optimic.src.textural_characteristics import disorientation_angles 43 | from optimic.src.textural_characteristics import type_of_grain_boundary 44 | from optimic.src.textural_characteristics import schmid_factor 45 | from optimic.src.textural_characteristics import available_required_texture 46 | 47 | def random_3d_testcase(store_folder, version, now, material, tessellation, \ 48 | dimension, size_of_simulation_box, spacing_length, seed_array_unique, \ 49 | required_texture, number_of_seeds, grain_size_distributions, \ 50 | number_of_neighbor, grain_boundary_area_distribution, junction_lengths, \ 51 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 52 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 53 | """ 54 | Execute all test conditions related to random_3d_testcase. 55 | 56 | Parameters 57 | ---------- 58 | store_folder: string 59 | Name of directory where output files are to be stored. 60 | 61 | version: string 62 | Current version of code. 63 | 64 | now: string 65 | Current time and date. 66 | 67 | material: string 68 | Material name of which microstructure is being tested. 69 | 70 | tessellation: dictionary 71 | Dictionary of tessellations data with following keys: 72 | 1. number_of_grains 73 | 2. number_of_faces_list 74 | 3. vertices_list 75 | 4. face_vertices_list 76 | 5. centroid_list 77 | 6. volume_list 78 | 7. normals_list 79 | 8. neighbors_list 80 | 9. face_area_list 81 | 10. number_of_edges_list 82 | 83 | dimension: integer 84 | Dimension of study (2 or 3) 85 | 86 | size_of_simulation_box: array of length 3 87 | Size of simulation box (array of length along X, Y, Z directions) 88 | 89 | spacing_length: float 90 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 91 | directions in Quasi-2D case. Also the spacing_length must be a perfect 92 | divisor of size of simulation box along all three directions. 93 | 94 | seed_array_unique: array of shape (number of grains, 3) 95 | Unique seed coordinates 96 | 97 | required_texture: array of length 3 98 | Specific texture to be used for all grains 99 | 100 | number_of_seeds: integer 101 | Number of seeds/grains. 102 | 103 | grain_size_distribution: 2D array 104 | An array of all the grain sizes in terms of radius. The 105 | first column is the grain number and second column consists of grain 106 | sizes. 107 | 108 | number_of_neighbor: 2D array 109 | An array comprising of data related to the number of 110 | neighbors of each grains. Column names are: Grain number, number of 111 | neighbors, grain indexes of neighbors. 112 | 113 | grain_boundary_area_distribution_ 2D array 114 | An array of consisting of columns Sr. No., Grain 1, 115 | Grain 2 and grain boundary area. 116 | 117 | junction_lengths: List of lists 118 | List of lists consisting of column names: Sr. no., Junction type, 119 | Junction lengths, grains with this junction. 120 | 121 | junction_angles_degrees: List of lists 122 | List of lists consisting of column names: Sr. No., Junction Type, 123 | 1st Junction angle, Grain containing the 1st junction angle, 124 | 2nd Junction angle, so on... 125 | 126 | distance_btw_grain_array: 2D array 127 | Symmetric array with rows and columns represented by grain numbers in 128 | ascending order and each element of the array representing distance 129 | between respective grain numbers. 130 | 131 | distance_btw_grain_1d: 1D array 132 | 1D array of distances between grains 133 | 134 | disorientation_angle: 2D array 135 | An array consisting of columns grain 1, grain 2, disorientation 136 | angle, disorientation axis. 137 | 138 | schmid_factors: 2D array 139 | An array consisting of Schmid Factor related data with column names as 140 | Grain no., Schmid factor, Slip plane and direction (Slip System). 141 | 142 | type_of_grain_boundaries: 2D array 143 | An array with the column names as grain 1, grain 2, rotation angle, 144 | rotation axis, type of csl (0 indicates normal grain boundary). 145 | 146 | log_level: string 147 | Logger level to be used. 148 | 149 | Returns 150 | ------- 151 | Function returns nothing. 152 | 153 | Output 154 | ------ 155 | 1. Seeds_data_without_orientations.txt in current working directory. 156 | 2. Seeds_data_with_orientations.txt in current working directory. 157 | 3. array_verification_file.txt in appropriate directory within specified 158 | storage_folder 159 | 160 | """ 161 | log = set_logger(name_str, 'log_data.log', log_level) 162 | ##Writing Seeds information without orientations to a file 163 | with open('seeds_data_without_orientations.txt', 'a+') as f: 164 | f.truncate(0) 165 | f.write("# X, Y, Z, W, OX, OY, OZ \n") 166 | np.savetxt(f, seed_array_unique, fmt='%.4f', delimiter= ',') 167 | 168 | ## Writing Seeds information with orientations to a file 169 | orientation_quaternion = sharp_texture_quaternions(1, required_texture, log_level) # Generating a random quaternion 170 | #orientation_quaternion = np.array([1, 0, 0, 0]) 171 | orientation_array = np.broadcast_to(orientation_quaternion, (seed_array_unique.shape[0], 4)) # Assigning same orientation to each grain 172 | seeds_data = np.concatenate((seed_array_unique, orientation_array), axis=1) # Concatenating seed coorinates and orientations 173 | 174 | with open('seeds_data_with_orientations.txt', 'a+') as f: 175 | f.truncate(0) 176 | f.write("# X, Y, Z, W, OX, OY, OZ \n") 177 | np.savetxt(f, seeds_data, fmt='%.4f', delimiter= ',') 178 | 179 | ## Reading Seeds data from the files 180 | with open('seeds_data_without_orientations.txt', 'r') as f: 181 | data = np.loadtxt(f, delimiter=',', comments='#') 182 | 183 | ## Extracting orientations data if available 184 | if data.shape[1] == 7: 185 | orientation_data = data[:, 3:7] 186 | else: orientation_data = None 187 | 188 | with open('seeds_data_with_orientations.txt', 'r') as f: 189 | data_orientation = np.loadtxt(f, delimiter=',', comments='#') 190 | seeds_data = data_orientation[:, :3] 191 | 192 | ## Extracting orientations data if available 193 | if data_orientation.shape[1] == 7: 194 | orientation_data = data_orientation[:, 3:7] 195 | else: orientation_data = None 196 | 197 | total_volume = 0 198 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 199 | total_volume += copy.deepcopy(tessellation['volume_list'][v]) 200 | 201 | try: 202 | assert seed_array_unique.shape[0] == number_of_seeds ## Checking if the number of random unique seeds are same as required 203 | assert np.isclose(total_volume, size_of_simulation_box*size_of_simulation_box*size_of_simulation_box) 204 | assert np.array_equal(seed_array_unique, data) 205 | assert np.array_equal(seed_array_unique, seeds_data) 206 | assert np.allclose(orientation_data, orientation_array, atol=1e-4) 207 | except AssertionError: 208 | log.exception('random_3d_testcase failed !!') 209 | 210 | ## Saving to array_verification_file.txt 211 | output_file_path = Path(store_folder, material, now, "Text_output", "array_verification_file.txt") 212 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 213 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 214 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 215 | output_file_path.parent.parent.mkdir(exist_ok=True) 216 | output_file_path.parent.mkdir(exist_ok=True) # checks if folder exists, if not then creates one 217 | 218 | with open(str(output_file_path), 'a+') as f: 219 | f.truncate(0) 220 | f.write("Verification matrix for seed_array read from file without orientations \n") 221 | np.savetxt(f, seed_array_unique - data, newline='\n', delimiter=',', fmt="%.4f") 222 | f.write("\n \n Verification matrix for seed_array read from file with orientations \n") 223 | np.savetxt(f, seed_array_unique - seeds_data, newline='\n', delimiter=',', fmt="%.4f") 224 | f.write("\n \n Verification matrix for orientations array read from file with orientations \n") 225 | np.savetxt(f, orientation_data - orientation_array, newline='\n', delimiter=',', fmt="%.4f") 226 | 227 | log.info('random_3d_testcase passed !!') 228 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # **OptiMic** 4 | ### **A tool to generate optimized polycrystalline microstructures for materials simulations** 5 | 6 | | | 7 | | :---: | 8 | | **Overview of generating tessellations** | 9 | 10 | | | 11 | | :---: | 12 | | | 13 | | **Overview of meshing process** | 14 | 15 | OptiMic is an open-source software to generate optimized microstructures in 2D or 3D, for finite element and atomistic simulations. It comprises of a feature to provide extensive control to the user on optimization through custom user defined cost functions. 16 | 17 | This was created as part of "Personal Programming Project (PPP)" coursework in "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, Germany. 18 | 19 | # **Quick Start** 20 | 21 | The tool can be directly cloned from the [**git repository**](https://gitlab.com/arun.prakash.mimm/optimic.git) to your desired directory. In order to install this package, navigate in the terminal to the directory `optimic`. 22 | 23 | Before starting, please ensure that you have statisfied all the [**requirements**](https://gitlab.com/arun.prakash.mimm/optimic/-/wikis/Home/Requirements#requirements) and most importantly, ensure that you have installed all the [**required libraries**](https://gitlab.com/arun.prakash.mimm/optimic/-/wikis/Home/Requirements/installing_libraries#installing-libraries). 24 | 25 | ## **Basic Usage** 26 | 27 | For detailed reference usage manual please [**click here**](https://gitlab.com/arun.prakash.mimm/optimic/-/wikis/Home/usage_manual/list_of_options/list_of_options#list-of-options). 28 | 29 | ### **Navigate to the directory and changing file permissions** 30 | 31 | First ensure that you are in the correct directory. `pwd` command can be used to find the current working directory. 32 | 33 | ```bash 34 | $ pwd 35 | /..some_directories../optimic 36 | ``` 37 | Once you are in the correct directory, the package can be installed by using: 38 | 39 | ```bash 40 | $ pip install . 41 | ``` 42 | ***Note:** Please notice that there is a dot (.) in the command above.* 43 | 44 | In order to execute the program, you can now use: 45 | 46 | ```bash 47 | $ optimic input-arguments 48 | ``` 49 | where input-arguments denote options. 50 | 51 | ### **Undertanding available options** 52 | 53 | It is better to have a grasp of the options available 54 | 55 | ```bash 56 | $ optimic main --help 57 | ``` 58 | The following would be displayed: 59 | ```bash 60 | ================================== 61 | ___ _ _ __ __ _ 62 | / _ \ _ __ | |_(_) \/ (_) ___ 63 | | | | | '_ \| __| | |\/| | |/ __| 64 | | |_| | |_) | |_| | | | | | (__ 65 | \___/| .__/ \__|_|_| |_|_|\___| 66 | |_| 67 | ================================== 68 | Optimized Microstructure Generator 69 | Copyright © 2020-2021 70 | Authors: P. H. Serrao, S. Sandfeld, A. Prakash 71 | Version: v2.0 72 | 73 | Usage: optimic main [OPTIONS] 74 | 75 | Options: 76 | -s, --size FLOAT... Size of simulation box along X, Y & Z 77 | direction in the format n n n [required] 78 | -dim, --dimension INTEGER Dimension of study ie; 2D or 3D in the 79 | format n where n is an integer 80 | -n, --number_seed INTEGER Number of seeds/grains in the format n 81 | -t, --target TEXT Target distribution file name as a string 82 | stored in the same directory where the 83 | package is executed from 84 | -c, --characteristic INTEGER The characteristic that has to be optimized 85 | in the format n where n corresponds to the 86 | integer number corresponding to the 87 | characteristic 88 | -m, --material TEXT The name of the material as a string 89 | -sdir, --stress_direction INTEGER... 90 | The direction of stress for computing the 91 | Schmid Factors 92 | -so, --sharp_orientation FLOAT... 93 | Required texture common to each grain in the 94 | format n n n as provided in the 95 | documentation 96 | -noopti, --no_optimization Flag to indicate if optimization is not to 97 | be performed 98 | -f, --face_flag This flag is to be used to indicate if a 99 | closed surface is to be used for 100 | visualization files for all grain in one 101 | file 102 | -ss, --seed_spacing TEXT Option to indicate if randomly placed seeds 103 | are required or regularly spaced seeds ie; 104 | cubic_2d, cubic_3d, etc [default: 105 | random_3d] 106 | -sl, --spacing_length FLOAT Option to specify the spacing length such 107 | that it is exactly a multiple of size of 108 | simulation box along all three directions 109 | [default: 1.0] 110 | -om, --optimization_method TEXT 111 | Method to be used for optimization 112 | [default: COBYLA] 113 | -skw, --skew_boundary Flag to indicate skewed boundary requirement 114 | -ucf, --user_cost_func TEXT Specify the user defined cost function file 115 | name. Refer documentation for file 116 | specifications 117 | -msh, --mesh TEXT Flag to indicate type of meshing required of 118 | the simulation box. Eg. hex (for 119 | Hexahedral), tet (for Tetrahedral), vis (for 120 | Visualization) 121 | -gms, --mesh_size FLOAT Provide global mesh size [default: 0.5] 122 | -mi, --max_iter INTEGER Provide maximum number of iterations during 123 | optimizytion. The objective function might 124 | be evaluated multiple times during each 125 | iteration. [default: 200] 126 | -rs, --rand_seed INTEGER Enter the seed value for Numpy random 127 | function 128 | -nb, --number_bins INTEGER Specify the number of bins [default: 10] 129 | -si, --save_interval INTEGER Intervals of iterations in which the seeds 130 | data is to be saved and live plot is to be 131 | extended [default: 100] 132 | -r, --restart INTEGER Restart optimization using seed positions of 133 | specified function evaluation count number. 134 | Specify -1 to use optimized seed positions. 135 | [default: 0] 136 | -deb, --debug Flag to activate Debug mode 137 | --help Show this message and exit. 138 | 139 | ``` 140 | 141 | **Execute the following command to view options available for executing tests.** 142 | 143 | ```bash 144 | $ optimic test --help 145 | ``` 146 | 147 | The following would be displayed: 148 | 149 | ```bash 150 | ================================== 151 | ___ _ _ __ __ _ 152 | / _ \ _ __ | |_(_) \/ (_) ___ 153 | | | | | '_ \| __| | |\/| | |/ __| 154 | | |_| | |_) | |_| | | | | | (__ 155 | \___/| .__/ \__|_|_| |_|_|\___| 156 | |_| 157 | ================================== 158 | Optimized Microstructure Generator 159 | Copyright © 2020-2021 160 | Authors: P. H. Serrao, S. Sandfeld, A. Prakash 161 | Version: v2.0 162 | 163 | Usage: optimic test [OPTIONS] 164 | 165 | Options: 166 | -nt, --name TEXT Enter the test case name that you want to execute. 167 | For eg; Cubic_2d, Cubic_3d, fcc_2d, fcc_3d, 168 | bcc_3d, random_3d, textural or ALL 169 | -f, --face_flag This flag is to be used to indicate if a closed 170 | surface is to be used for visualization files for 171 | all grain in one file 172 | -rs, --rand_seed INTEGER Enter the seed value for Numpy random function 173 | -deb, --debug Flag to activate Debug mode 174 | --help Show this message and exit. 175 | 176 | ``` 177 | 178 | ### **Generate microstructure without optimization** 179 | 180 | The microstructure with Cubic spacing in 2D without optimization can be obtained by using: 181 | 182 | ```bash 183 | $ optimic main -s 10 10 10 -dim 2 -m steel -sdir 0 1 0 -ss cubic_2d -noopti 184 | ``` 185 | Here `-noopti` indicates that optimization is not required. The `cubic_2d` can also be replaced with `cubic_3d`, `fcc_2d`, `fcc_3d`, `bcc_3d`, or `random_3d` along with appropriate value for `-dim` option representing the dimension. 186 | 187 | ### **Generate microstructure with optimization** 188 | 189 | The microstructure with Random spacing in 3D with optimization can be obtained by using: 190 | 191 | ```bash 192 | $ optimic main -s 10 10 3 -dim 3 -m steel -sdir 0 1 0 -ss random_3d -t user_grain_size_distribution.txt -c 0 -n 10 193 | ``` 194 | Here `-n` represents the number of seeds required. The results are stored in the directory `visualization_files`. 195 | 196 | ### **Generate microstructure with meshing but without optimization** 197 | 198 | Here we would be again using the case of `cubic_2d` seed spacing. 199 | 200 | ```bash 201 | $ optimic main -s 10 10 10 -dim 2 -m steel -sdir 0 1 0 -ss cubic_2d -noopti -msh hex 202 | ``` 203 | 204 | Here `-msh hex` represents the meshing of obtained configuration using hexahedral meshes. The `hex` keyword can also be replaced with `tet` for tetrahedral elements or `vis` to generate tetrahedral elements for the meshing of raw configuration obtained directly without preprocessing into a cuboid, just for visualization purposes. 205 | 206 | **For more details regarding the possibilities of microstructure generation using this tool, please refer the [reference usage manual](https://gitlab.com/arun.prakash.mimm/optimic/-/wikis/Home/usage_manual/list_of_options/list_of_options#list-of-options).** 207 | 208 |
209 | -------------------------------------------------------------------------------- /optimic/src/create_vtk_files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | create_vtk_files.py 4 | 5 | Module to create VTK files for visualization. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def create_vtk_file_all_grains(material_name, tessellation, store_folder, face_flag, now, skewed_boundary_flag, all_vertices_list, log_level): 41 | """ 42 | The function creates a directory "vtk_file_all_grains" if it doesnt 43 | exist in the 'visualization_files' directorywithin appropriate 44 | sub-directories. An VTK file consisting data related to all the grains is 45 | saved in this directory. 46 | 47 | Parameters 48 | ---------- 49 | material_name: string 50 | Name of the material of which microstructure is being generated. 51 | 52 | tessellation: dictionary 53 | Dictionary consisting of data related to tessellations generated. 54 | 55 | store_folder: string 56 | Sub-directory name (output/output_test) in which output data would be 57 | stored. 58 | 59 | face_flag: boolean 60 | Flag to specify if opaque surfaces are to be used instead of transparent. 61 | 62 | now: string 63 | Current time and date. 64 | 65 | skewed_boundary_flag: boolean 66 | Flag to specify if skewed grain boundaries are required. Only functional 67 | in quasi-2D case. 68 | 69 | all_vertices_list: list 70 | List of vertices of skewed faces in appropriate sequence. 71 | 72 | log_level: string 73 | Logger level to be used. 74 | 75 | Output 76 | ------ 77 | The functions saves VTK file consisting of all the vertices and the line 78 | connectivity data for all the vertices in the respective folder. 79 | """ 80 | 81 | log = set_logger(name_str, 'log_data.log', log_level) 82 | log.info('Creating VTK file of entire configuration') 83 | 84 | ## Checking if opaque surfaces are required or transparent 85 | if face_flag: 86 | type_of_surface = 7 # 7 indicates opaque surface 87 | else: 88 | type_of_surface = 4 # 4 indicates connection of all the vertices by polyline 89 | 90 | ## Creating Folder and assigning the output file path 91 | output_file_path = Path(store_folder, material_name, now, "vtk_file_all_grains", "{:s}.vtk".format(material_name + "_morphology")) 92 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 93 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 94 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 95 | output_file_path.parent.parent.mkdir(exist_ok=True) 96 | output_file_path.parent.mkdir(exist_ok=True) # checks if folder exists, if not then creates one 97 | 98 | ## Using generator statement to extract data from all cells of the tessellation 99 | if skewed_boundary_flag: 100 | grain_vertices = all_vertices_list # Using skewed vertices list 101 | else: 102 | grain_vertices = copy.deepcopy(tessellation['vertices_list']) #[v.vertices() for v in tessellation] # all the vertices of each grains 103 | 104 | number_of_grain_vertices = np.sum([len(i) for i in grain_vertices]) 105 | grain_faces = copy.deepcopy(tessellation['face_vertices_list']) #[v.face_vertices() for v in tessellation] 106 | number_of_grain_faces = np.sum([len(i) for i in grain_faces]) 107 | 108 | ## Writing the required commands to the file 109 | with open(str(output_file_path), 'a+') as f: 110 | f.truncate(0) 111 | 112 | ## Writing the Header lines 113 | f.write("# vtk DataFile Version 3.0 \n") 114 | f.write("Morphology of all grains. Created using 'OptiMic: A tool to generate optimized polycrystalline microstructures for materials simulations'. Authors: Serrao Prince Henry, Arun Prakash. Distributed under GNU General Public License. \n") 115 | f.write("ASCII \n") 116 | f.write("DATASET UNSTRUCTURED_GRID \n") 117 | f.write("POINTS " + str(number_of_grain_vertices) + " float \n") 118 | 119 | ## Writing all vertices to the file 120 | vertices_indices = [0] 121 | for vertex in grain_vertices: 122 | vertices_indices.append(len(vertex) + vertices_indices[-1]) 123 | for vertex_coords_list in vertex: 124 | vertex_coords = np.array(vertex_coords_list) 125 | f.write (str(vertex_coords).strip('[').strip(']').lstrip(' ').rstrip(' ') + "\n") 126 | f.write("\n \n") 127 | 128 | ## Writing the Cells (Face vertices) data to file 129 | sum = 0 130 | for faces in grain_faces: 131 | for face_indices in faces: 132 | sum += len(face_indices) 133 | 134 | f.write("CELLS " + str(number_of_grain_faces) + " " + str((number_of_grain_faces) + sum) + "\n") 135 | 136 | for grain_number, faces in enumerate(grain_faces): 137 | for face_indices in faces: 138 | face_indice = np.array(face_indices) 139 | f.write(str(len(face_indices)) + " " + str(face_indice + vertices_indices[grain_number]).strip('[').strip(']') + "\n") 140 | f.write("\n \n") 141 | 142 | ## Writing Cell Type data to file 143 | f.write("CELL_TYPES " + str(number_of_grain_faces) + "\n") 144 | for i in range(number_of_grain_faces): 145 | f.write(str(type_of_surface) + "\n") 146 | 147 | log.info('Successfully created VTK file of entire configuration') 148 | 149 | 150 | def create_vtk_file_individual_grains(material_name, tessellation, store_folder, now, skewed_boundary_flag, all_vertices_list, log_level): 151 | """ 152 | The function creates a directory "vtk_file_individual_grains" if it doesnt 153 | exist in the 'visualization_files' directory within appropriate 154 | sub-directories. Individual VTK files consisting data related to respective 155 | grain is saved in this folder. By default only opaque surfaces are created 156 | for individual grains. 157 | 158 | Parameters 159 | ---------- 160 | material_name: string 161 | Name of the material of which microstructure is being generated. 162 | 163 | tessellation: dictionary 164 | Dictionary consisting of data related to tessellations generated. 165 | 166 | store_folder: string 167 | Sub-directory name (output/output_test) in which output data would be 168 | stored. 169 | 170 | now: string 171 | Current time and date. 172 | 173 | skewed_boundary_flag: boolean 174 | Flag to specify if skewed grain boundaries are required. Only functional 175 | in quasi-2D case. 176 | 177 | all_vertices_list: list 178 | List of vertices of skewed faces in appropriate sequence. 179 | 180 | log_level: string 181 | Logger level to be used. 182 | 183 | Output 184 | ------ 185 | The functions saves individual VTK files consisting of all the vertices and 186 | the line connectivity data for all the vertices in the respective folder. 187 | """ 188 | 189 | log = set_logger(name_str, 'log_data.log', log_level) 190 | log.info('Creating VTK files of individual grains') 191 | 192 | if skewed_boundary_flag: 193 | grain_vertices = all_vertices_list # Using skewed vertices list 194 | else: 195 | grain_vertices = copy.deepcopy(tessellation['vertices_list']) #[v.vertices() for v in tessellation] # all the vertices of each grains 196 | grain_faces = copy.deepcopy(tessellation['face_vertices_list']) #[v.face_vertices() for v in tessellation] 197 | 198 | for i in range(copy.deepcopy(tessellation['number_of_grains'])): 199 | 200 | log.debug('Creating VTK file of grain no. ' + str(i)) 201 | 202 | ## Creating Folder and assigning the output file path 203 | output_file_path = Path(store_folder, material_name, now, "vtk_file_individual_grains", "{:s}.vtk".format("grain_" + str(i+1))) 204 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 205 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 206 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 207 | output_file_path.parent.parent.mkdir(exist_ok=True) 208 | output_file_path.parent.mkdir(exist_ok=True) 209 | 210 | number_of_grain_vertices = len(grain_vertices[i]) 211 | number_of_grain_faces = len(grain_faces[i]) 212 | 213 | with open(str(output_file_path), 'a+') as f: 214 | f.truncate(0) 215 | 216 | ## Writing the Header lines 217 | f.write("# vtk DataFile Version 3.0 \n") 218 | f.write("Morphology of all grains. Created using 'OptiMic: A tool to generate optimized polycrystalline microstructures for materials simulations'. Authors: Serrao Prince Henry, Arun Prakash. Distributed under GNU General Public License. \n") 219 | f.write("ASCII \n") 220 | f.write("DATASET UNSTRUCTURED_GRID \n") 221 | f.write("POINTS " + str(number_of_grain_vertices) + " float \n") 222 | 223 | ## Writing all vertices to the file 224 | for vertex_list in grain_vertices[i]: 225 | vertex = np.array(vertex_list) 226 | f.write (str(vertex).strip('[').strip(']') + "\n") 227 | f.write("\n \n") 228 | 229 | ## Writing the Cells (Face vertices) data to file 230 | sum = 0 231 | for faces in grain_faces[i]: 232 | sum += len(faces) 233 | 234 | f.write("CELLS " + str(number_of_grain_faces) + " " + str((number_of_grain_faces) + sum) + "\n") 235 | 236 | for faces in grain_faces[i]: 237 | face_indice = np.array(faces) 238 | f.write(str(len(faces)) + " " + str(face_indice).strip('[').strip(']') + "\n") 239 | f.write("\n \n") 240 | 241 | ## Writing Cell Type data to file 242 | f.write("CELL_TYPES " + str(number_of_grain_faces) + "\n") 243 | for i in range(number_of_grain_faces): 244 | f.write(str(7) + "\n") 245 | 246 | log.info('Successfully created VTK files of all grains individually') -------------------------------------------------------------------------------- /optimic/src/create_obj_files.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | create_obj_files.py 4 | 5 | Module to create OBJ files for visualization. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 16 November 2019 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.set_logger import set_logger 38 | name_str = __name__ 39 | 40 | def create_obj_file_all_grains(material_name, tessellation, store_folder, face_flag, now, skewed_boundary_flag, all_vertices_list, log_level): 41 | """ 42 | The function creates a directory "obj_file_all_grains" if it doesnt 43 | exist in the 'visualization_files' directorywithin appropriate 44 | sub-directories. An OBJ file consisting data related to all the grains is 45 | saved in this directory. 46 | 47 | Parameters 48 | ---------- 49 | material_name: string 50 | Name of the material of which microstructure is being generated. 51 | 52 | tessellation: dictionary 53 | Dictionary consisting of data related to tessellations generated. 54 | 55 | store_folder: string 56 | Sub-directory name (output/output_test) in which output data would be 57 | stored. 58 | 59 | face_flag: boolean 60 | Flag to specify if opaque surfaces are to be used instead of transparent. 61 | 62 | now: string 63 | Current time and date. 64 | 65 | skewed_boundary_flag: boolean 66 | Flag to specify if skewed grain boundaries are required. Only functional 67 | in quasi-2D case. 68 | 69 | all_vertices_list: list 70 | List of vertices of skewed faces in appropriate sequence. 71 | 72 | log_level: string 73 | Logger level to be used. 74 | 75 | Output 76 | ------ 77 | The functions saves OBJ file consisting of all the vertices and the line 78 | connectivity data for all the vertices in the respective folder. 79 | """ 80 | 81 | log = set_logger(name_str, 'log_data.log', log_level) 82 | log.info('Creating OBJ file of entire configuration') 83 | ## Checking if opaque surfaces are required or transparent 84 | if face_flag: 85 | type_of_surface = "f " # 'f' indicates opaque face 86 | else: 87 | type_of_surface = "l " # 'l' indicates connection of vertices by polyline 88 | 89 | ## Creating Folder and assigning the output file path 90 | output_file_path = Path(store_folder, material_name, now, "obj_file_all_grains", "{:s}.obj".format(material_name + "_morphology")) 91 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 92 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 93 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 94 | output_file_path.parent.parent.mkdir(exist_ok=True) 95 | output_file_path.parent.mkdir(exist_ok=True) # checks if folder exists, if not then creates one 96 | 97 | 98 | ## Using generator statement to extract data from all cells of the tessellation 99 | if skewed_boundary_flag: 100 | grain_vertices = all_vertices_list 101 | else: 102 | grain_vertices = copy.deepcopy(tessellation['vertices_list']) #[v.vertices() for v in tessellation] # all the vertices of each grains 103 | grain_faces = copy.deepcopy(tessellation['face_vertices_list']) #[v.face_vertices() for v in tessellation] 104 | 105 | ## Writing the required commands of the OBJ format to the file 106 | with open(str(output_file_path), 'a+') as f: 107 | 108 | f.truncate(0) # Deleting all contents of the file 109 | f.write("# All grains morphology \n") 110 | 111 | f.write("# " + "{:s}.obj".format(material_name + "_morphology") + """# 112 | # This was created as part of "Personal Programming Project (PPP)" coursework in 113 | # "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 114 | # Germany. 115 | # 116 | # For reporting bugs/issues: 117 | # 118 | # @authors: Serrao Prince Henry, Arun Prakash 119 | # @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 120 | # Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 121 | # 122 | # This file is part of OptiMic. 123 | # 124 | # OptiMic is free software: you can redistribute it and/or modify 125 | # it under the terms of the GNU General Public License as published by 126 | # the Free Software Foundation, either version 3 of the License, or 127 | # (at your option) any later version. 128 | # 129 | # OptiMic is distributed in the hope that it will be useful, 130 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 131 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 132 | # GNU General Public License for more details. 133 | # 134 | # You should have received a copy of the GNU General Public License 135 | # along with OptiMic. If not, see . \n""") 136 | 137 | f.write("################################################################################\n") 138 | 139 | f.write('# Date and time [YYYYMMDD_HHMMSS]: ' + now) 140 | 141 | f.write('\n# Command line input: ' + " ".join(sys.argv)) 142 | 143 | f.write("""\n# This file contains data related to: 144 | # 1. Morphology of generated microstructure in Wavefront OBJ format\n""") 145 | 146 | ## Writing all vertices to the file 147 | vertices_indices = [0] 148 | for vertex in grain_vertices: 149 | vertices_indices.append(len(vertex) + vertices_indices[-1]) 150 | for vertex_coords_list in vertex: 151 | vertex_coords = np.array(vertex_coords_list) 152 | f.write ("v " + str(vertex_coords).strip('[').strip(']') + "\n") 153 | 154 | ## Writing line connectivity data for all the faces of each cell 155 | for grain_number, faces in enumerate(grain_faces): 156 | for face_indices in faces: 157 | face_indice = np.array(face_indices) 158 | f.write(type_of_surface + str(face_indice + vertices_indices[grain_number] + 1).strip('[').strip(']') + "\n") 159 | 160 | log.info('Successfully created OBJ file of entire configuration') 161 | 162 | def create_obj_file_individual_grains(material_name, tessellation, store_folder, now, skewed_boundary_flag, all_vertices_list, log_level): 163 | """ 164 | The function creates a directory "obj_file_individual_grains" if it doesnt 165 | exist in the 'visualization_files' directory within appropriate 166 | sub-directories. Individual OBJ files consisting data related to respective 167 | grain is saved in this folder. By default only opaque surfaces are created 168 | for individual grains. 169 | 170 | Parameters 171 | ---------- 172 | material_name: string 173 | Name of the material of which microstructure is being generated. 174 | 175 | tessellation: dictionary 176 | Dictionary consisting of data related to tessellations generated. 177 | 178 | store_folder: string 179 | Sub-directory name (output/output_test) in which output data would be 180 | stored. 181 | 182 | now: string 183 | Current time and date. 184 | 185 | skewed_boundary_flag: boolean 186 | Flag to specify if skewed grain boundaries are required. Only functional 187 | in quasi-2D case. 188 | 189 | all_vertices_list: list 190 | List of vertices of skewed faces in appropriate sequence. 191 | 192 | log_level: string 193 | Logger level to be used. 194 | 195 | Output 196 | ------ 197 | The functions saves individual OBJ files consisting of all the vertices and 198 | the line connectivity data for all the vertices in the respective folder. 199 | """ 200 | 201 | log = set_logger(name_str, 'log_data.log', log_level) 202 | log.info('Creating OBJ files of individual grains') 203 | 204 | ## If skewed boundary is required then modified vertices list is used 205 | if skewed_boundary_flag: 206 | grain_vertices = all_vertices_list 207 | else: 208 | grain_vertices = copy.deepcopy(tessellation['vertices_list']) #[v.vertices() for v in tessellation] # all the vertices of each grains 209 | grain_faces = copy.deepcopy(tessellation['face_vertices_list']) #[v.face_vertices() for v in tessellation] 210 | 211 | for i in range(copy.deepcopy(tessellation['number_of_grains'])): 212 | 213 | log.debug('Creating OBJ file of grain no. ' + str(i)) 214 | 215 | ## Creating Folder and assigning the output file path 216 | output_file_path = Path(store_folder, material_name, now, "obj_file_individual_grains", "{:s}.obj".format("grain_" + str(i+1))) 217 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 218 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 219 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 220 | output_file_path.parent.parent.mkdir(exist_ok=True) 221 | output_file_path.parent.mkdir(exist_ok=True) 222 | 223 | with open(str(output_file_path), 'a+') as f: 224 | f.truncate(0) 225 | f.write("# Individual grain morphology \n") 226 | 227 | f.write("# " + "{:s}.obj".format("grain_" + str(i+1)) + """# 228 | # This was created as part of "Personal Programming Project (PPP)" coursework in 229 | # "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 230 | # Germany. 231 | # 232 | # For reporting bugs/issues: 233 | # 234 | # @authors: Serrao Prince Henry, Arun Prakash 235 | # @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 236 | # Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 237 | # 238 | # This file is part of OptiMic. 239 | # 240 | # OptiMic is free software: you can redistribute it and/or modify 241 | # it under the terms of the GNU General Public License as published by 242 | # the Free Software Foundation, either version 3 of the License, or 243 | # (at your option) any later version. 244 | # 245 | # OptiMic is distributed in the hope that it will be useful, 246 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 247 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 248 | # GNU General Public License for more details. 249 | # 250 | # You should have received a copy of the GNU General Public License 251 | # along with OptiMic. If not, see . \n""") 252 | 253 | f.write("################################################################################\n") 254 | 255 | f.write('# Date and time [YYYYMMDD_HHMMSS]: ' + now) 256 | 257 | f.write('\n# Command line input: ' + " ".join(sys.argv)) 258 | 259 | f.write("""\n# This file contains data related to: 260 | # 1. Morphology of generated microstructure in Wavefront OBJ format\n""") 261 | 262 | 263 | for vertex_list in grain_vertices[i]: 264 | vertex = np.array(vertex_list) 265 | f.write ("v " + str(vertex).strip('[').strip(']') + "\n") 266 | f.write("\n \n") 267 | 268 | for faces in grain_faces[i]: 269 | face_indice = np.array(faces) 270 | f.write("f " + str(face_indice + 1).strip('[').strip(']') + "\n") 271 | f.write("\n \n") 272 | 273 | log.info('Successfully created OBJ files of all grains individually') -------------------------------------------------------------------------------- /optimic/test_cases/two_seed/two_seed_testcase.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | two_seed_testcase.py 4 | 5 | Module to test some features of program for TWO SEEDS. 6 | 7 | This was created as part of "Personal Programming Project (PPP)" coursework in 8 | "Computation Materials Science (CMS)" M. Sc program at TU Bergakademie Freiberg, 9 | Germany. 10 | 11 | For reporting bugs/issues: 12 | 13 | @authors: Serrao Prince Henry, Arun Prakash 14 | @email: prince.serrao.code@gmail.com, arun.prakash@imfd.tu-freiberg.de 15 | created: 31 March 2020 16 | Copyright © 2020 by Serrao Prince Henry, Dr. Arun Prakash 17 | 18 | This file is part of OptiMic. 19 | 20 | OptiMic is free software: you can redistribute it and/or modify 21 | it under the terms of the GNU General Public License as published by 22 | the Free Software Foundation, either version 3 of the License, or 23 | (at your option) any later version. 24 | 25 | OptiMic is distributed in the hope that it will be useful, 26 | but WITHOUT ANY WARRANTY; without even the implied warranty of 27 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 28 | GNU General Public License for more details. 29 | 30 | You should have received a copy of the GNU General Public License 31 | along with OptiMic. If not, see . 32 | 33 | """ 34 | 35 | from optimic.src.main_import_statements import * 36 | 37 | from optimic.src.textural_characteristics import disorientation_angles 38 | from optimic.src.textural_characteristics import type_of_grain_boundary 39 | 40 | from optimic.src.set_logger import set_logger 41 | name_str = __name__ 42 | 43 | def two_seed_testcase(store_folder, version, now, material, tessellation, \ 44 | dimension, size_of_simulation_box, spacing_length, length_z, \ 45 | required_texture, rand_quat_flag, grain_size_distributions, \ 46 | number_of_neighbor, grain_boundary_area_distribution, junction_lengths, \ 47 | junction_angles_degrees, distance_btw_grain_array, distance_btw_grain_1d, \ 48 | disorientation_angle, schmid_factors, type_of_grain_boundaries, log_level): 49 | """ 50 | Execute all test conditions related to two_seed_testcase. 51 | 52 | Parameters 53 | ---------- 54 | store_folder: string 55 | Name of directory where output files are to be stored. 56 | 57 | version: string 58 | Current version of code. 59 | 60 | now: string 61 | Current time and date. 62 | 63 | material: string 64 | Material name of which microstructure is being tested. 65 | 66 | tessellation: dictionary 67 | Dictionary of tessellations data with following keys: 68 | 1. number_of_grains 69 | 2. number_of_faces_list 70 | 3. vertices_list 71 | 4. face_vertices_list 72 | 5. centroid_list 73 | 6. volume_list 74 | 7. normals_list 75 | 8. neighbors_list 76 | 9. face_area_list 77 | 10. number_of_edges_list 78 | 79 | dimension: integer 80 | Dimension of study (2 or 3) 81 | 82 | size_of_simulation_box: float 83 | Size of simulation box (array of length along X, Y, Z directions) 84 | 85 | spacing_length: float 86 | Spacing between seeds along X, Y & Z in 3D case and along X & Y 87 | directions in Quasi-2D case. Also the spacing_length must be a perfect 88 | divisor of size of simulation box along all three directions. 89 | 90 | length_z: float 91 | Size of simulation box along Z axis. 92 | 93 | required_texture: array of length 3 94 | Specific texture to be used for all grains 95 | 96 | rand_quat_flag: boolean 97 | Flag to indicate that random orientations are to be assigned to all 98 | grains. 99 | 100 | grain_size_distribution: 2D array 101 | An array of all the grain sizes in terms of radius. The 102 | first column is the grain number and second column consists of grain 103 | sizes. 104 | 105 | number_of_neighbor: 2D array 106 | An array comprising of data related to the number of 107 | neighbors of each grains. Column names are: Grain number, number of 108 | neighbors, grain indexes of neighbors. 109 | 110 | grain_boundary_area_distribution_ 2D array 111 | An array of consisting of columns Sr. No., Grain 1, 112 | Grain 2 and grain boundary area. 113 | 114 | junction_lengths: List of lists 115 | List of lists consisting of column names: Sr. no., Junction type, 116 | Junction lengths, grains with this junction. 117 | 118 | junction_angles_degrees: List of lists 119 | List of lists consisting of column names: Sr. No., Junction Type, 120 | 1st Junction angle, Grain containing the 1st junction angle, 121 | 2nd Junction angle, so on... 122 | 123 | distance_btw_grain_array: 2D array 124 | Symmetric array with rows and columns represented by grain numbers in 125 | ascending order and each element of the array representing distance 126 | between respective grain numbers. 127 | 128 | distance_btw_grain_1d: 1D array 129 | 1D array of distances between grains 130 | 131 | disorientation_angle: 2D array 132 | An array consisting of columns grain 1, grain 2, disorientation 133 | angle, disorientation axis. 134 | 135 | schmid_factors: 2D array 136 | An array consisting of Schmid Factor related data with column names as 137 | Grain no., Schmid factor, Slip plane and direction (Slip System). 138 | 139 | type_of_grain_boundaries: 2D array 140 | An array with the column names as grain 1, grain 2, rotation angle, 141 | rotation axis, type of csl (0 indicates normal grain boundary). 142 | 143 | log_level: string 144 | Logger level to be used. 145 | 146 | Returns 147 | ------- 148 | Function returns nothing. 149 | 150 | Output 151 | ------ 152 | array_verification_file.txt in appropriate directory within specified 153 | storage_folder 154 | """ 155 | log = set_logger(name_str, 'log_data.log', log_level) 156 | limit = np.array([size_of_simulation_box, size_of_simulation_box, size_of_simulation_box]) 157 | 158 | total_volume = 0 159 | assert np.isclose(copy.deepcopy(tessellation['volume_list'][0]) , (size_of_simulation_box*size_of_simulation_box*length_z)/2) ## Testing the volume of each cell 160 | assert np.isclose(copy.deepcopy(tessellation['volume_list'][1]) , (size_of_simulation_box*size_of_simulation_box*length_z)/2) ## Testing the volume of each cell 161 | for v in range(copy.deepcopy(tessellation['number_of_grains'])): 162 | total_volume += copy.deepcopy(tessellation['volume_list'][v]) 163 | assert np.isclose(total_volume, size_of_simulation_box*size_of_simulation_box*length_z) ## Testing the total volume of the cells 164 | assert np.all(np.isclose(distance_btw_grain_1d, size_of_simulation_box/2)) 165 | 166 | #tessellation = create_tessellations(seed_array_unique, limit) 167 | 168 | # Σ = 15 grain boundary orientations 169 | orientation_data = np.array([[1, 0, 0, 0], [0.7745967, 0.5163978, 0.2581989, 0.2581989]]) 170 | skewed_boundary_flag = False 171 | disorientation_angle, orientation_data = disorientation_angles(dimension, limit, skewed_boundary_flag, required_texture, rand_quat_flag, orientation_data, tessellation, log_level) 172 | type_of_grain_boundaries_sigma_15, orientation_data = type_of_grain_boundary(required_texture, rand_quat_flag, orientation_data, tessellation, dimension, limit, skewed_boundary_flag, log_level) 173 | assert (np.all(type_of_grain_boundaries_sigma_15[:, 6] == 15)) 174 | assert (np.all(np.isclose(disorientation_angle[:, 2], 48.2, atol=1e-1))) 175 | 176 | ## Saving to array_verification_file.txt 177 | output_file_path = Path(store_folder, material, now, "Text_output", "array_verification_file.txt") 178 | output_file_path.parent.parent.parent.parent.parent.mkdir(exist_ok=True) 179 | output_file_path.parent.parent.parent.parent.mkdir(exist_ok=True) 180 | output_file_path.parent.parent.parent.mkdir(exist_ok=True) 181 | output_file_path.parent.parent.mkdir(exist_ok=True) 182 | output_file_path.parent.mkdir(exist_ok=True) # checks if folder exists, if not then creates one 183 | 184 | with open(str(output_file_path), 'a+') as f: 185 | f.truncate(0) 186 | f.write("Verification matrix for disorientation matrix for Sigma 15 GB type \n") 187 | f.write("# Grain 1, Grain 2, Disorientation angle, Disorientation axis \n") 188 | np.savetxt(f, disorientation_angle, newline='\n', delimiter=',', fmt="%.4f") 189 | f.write("\n \n Verification matrix for Type of GB for Sigma 15 GB type \n") 190 | f.write("# Grain 1, Grain 2, Misorientation angle, Misorientation axis, Type of Grain Boundary \n") 191 | np.savetxt(f, type_of_grain_boundaries_sigma_15, newline='\n', delimiter=',', fmt="%.4f") 192 | 193 | # Σ = 5 grain boundary orientations 194 | orientation_data = np.array([[1, 0, 0, 0], [0.6710739, 0.6706129, 0.2235376, 0.2235376]]) 195 | skewed_boundary_flag = False 196 | disorientation_angle, orientation_data = disorientation_angles(dimension, limit, skewed_boundary_flag, required_texture, rand_quat_flag, orientation_data, tessellation, log_level) 197 | type_of_grain_boundaries_sigma_5, orientation_data = type_of_grain_boundary(required_texture, rand_quat_flag, orientation_data, tessellation, dimension, limit, skewed_boundary_flag, log_level) 198 | assert (np.all(type_of_grain_boundaries_sigma_5[:, 6] == 5)) 199 | assert (np.all(np.isclose(disorientation_angle[:, 2], 36.9, atol=1e-1))) 200 | 201 | ## Saving to array_verification_file.txt 202 | with open(str(output_file_path), 'a+') as f: 203 | f.write("\n \n Verification matrix for disorientation matrix for Sigma 5 GB type \n") 204 | f.write("# Grain 1, Grain 2, Disorientation angle, Disorientation axis \n") 205 | np.savetxt(f, disorientation_angle, newline='\n', delimiter=',', fmt="%.4f") 206 | f.write("\n \n Verification matrix for Type of GB for Sigma 5 GB type \n") 207 | f.write("# Grain 1, Grain 2, Misorientation angle, Misorientation axis, Type of Grain Boundary \n") 208 | np.savetxt(f, type_of_grain_boundaries_sigma_5, newline='\n', delimiter=',', fmt="%.4f") 209 | 210 | # Σ = 3 grain boundary orientations 211 | orientation_data = np.array([[1, 0, 0, 0], [0.8166416, 0.4081033, 0.4081033, 0]]) 212 | skewed_boundary_flag = False 213 | disorientation_angle, orientation_data = disorientation_angles(dimension, limit, skewed_boundary_flag, required_texture, rand_quat_flag, orientation_data, tessellation, log_level) 214 | type_of_grain_boundaries_sigma_3, orientation_data = type_of_grain_boundary(required_texture, rand_quat_flag, orientation_data, tessellation, dimension, limit, skewed_boundary_flag, log_level) 215 | assert (np.all(type_of_grain_boundaries_sigma_3[:, 6] == 3)) 216 | assert (np.all(np.isclose(disorientation_angle[:, 2], 60.0, atol=1e-1))) 217 | 218 | ## Saving to array_verification_file.txt 219 | with open(str(output_file_path), 'a+') as f: 220 | f.write("\n \n Verification matrix for disorientation matrix for Sigma 3 GB type \n") 221 | f.write("# Grain 1, Grain 2, Disorientation angle, Disorientation axis \n") 222 | np.savetxt(f, disorientation_angle, newline='\n', delimiter=',', fmt="%.4f") 223 | f.write("\n \n Verification matrix for Type of GB for Sigma 3 GB type \n") 224 | f.write("# Grain 1, Grain 2, Misorientation angle, Misorientation axis, Type of Grain Boundary \n") 225 | np.savetxt(f, type_of_grain_boundaries_sigma_3, newline='\n', delimiter=',', fmt="%.4f") 226 | 227 | # Σ = 7 grain boundary orientations 228 | orientation_data = np.array([[1, 0, 0, 0], [0.8017756, 0.5345322, 0.2672661, 0]]) 229 | skewed_boundary_flag = False 230 | disorientation_angle, orientation_data = disorientation_angles(dimension, limit, skewed_boundary_flag, required_texture, rand_quat_flag, orientation_data, tessellation, log_level) 231 | type_of_grain_boundaries_sigma_7, orientation_data = type_of_grain_boundary(required_texture, rand_quat_flag, orientation_data, tessellation, dimension, limit, skewed_boundary_flag, log_level) 232 | assert (np.all(type_of_grain_boundaries_sigma_7[:, 6] == 7)) 233 | assert (np.all(np.isclose(disorientation_angle[:, 2], 38.2, atol=1e-1))) 234 | 235 | ## Saving to array_verification_file.txt 236 | with open(str(output_file_path), 'a+') as f: 237 | f.write("\n \n Verification matrix for disorientation matrix for Sigma 7 GB type \n") 238 | f.write("# Grain 1, Grain 2, Disorientation angle, Disorientation axis \n") 239 | np.savetxt(f, disorientation_angle, newline='\n', delimiter=',', fmt="%.4f") 240 | f.write("\n \n Verification matrix for Type of GB for Sigma 7 GB type \n") 241 | f.write("# Grain 1, Grain 2, Misorientation angle, Misorientation axis, Type of Grain Boundary \n") 242 | np.savetxt(f, type_of_grain_boundaries_sigma_7, newline='\n', delimiter=',', fmt="%.4f") 243 | 244 | log.info('two_seed_testcase passed !!') --------------------------------------------------------------------------------