├── .gitignore
├── .pdm-python
├── .readthedocs.yaml
├── LICENSE
├── LICENSE.txt
├── MANIFEST.in
├── README.md
├── README.rst
├── archive
├── setup-org.py
├── setup-template.py
└── setup.py
├── build-package.py
├── docs
├── Makefile
├── make.bat
├── requirements.txt
└── source
│ ├── calfem.logo.bw.svg
│ ├── calfem_examples.rst
│ ├── calfem_mesh_guide.rst
│ ├── calfem_reference.rst
│ ├── conf.py
│ ├── developer.rst
│ ├── examples
│ ├── cfeditor.ui
│ ├── exm1.ipynb
│ ├── exm10.ipynb
│ ├── exm13.ipynb
│ ├── exm2.ipynb
│ ├── exm3.ipynb
│ ├── exm6.ipynb
│ ├── exm7.ipynb
│ ├── exmqt1.ui
│ ├── exmqt11.ui
│ ├── exmqt6.ui
│ ├── exs2.ipynb
│ ├── exs3.ipynb
│ ├── exs4.ipynb
│ └── exs7.ipynb
│ ├── exs1.rst
│ ├── images
│ ├── SVG
│ │ └── Rityta 1.svg
│ ├── bars1.png
│ ├── bars2.png
│ ├── bars3.png
│ ├── calfem.logo.ai
│ ├── calfem.logo.png
│ ├── calfem.logo.svg
│ ├── calfem.logo.sw.svg
│ ├── exm0_2.png
│ ├── exs1-1-rev1.png
│ ├── exs1-1.png
│ ├── exs2.png
│ ├── frame_and_bars.png
│ ├── mesh1.png
│ ├── mesh2.png
│ ├── mesh3.png
│ └── tut2-1.png
│ ├── index.rst
│ └── installation.rst
├── example_outputs.py
├── examples
├── example1.py
├── exd_beam2_b.py
├── exd_beam2_m.py
├── exd_beam2_t.py
├── exd_beam2_tr.py
├── exe_stress_2d_editor.py
├── exm_circle_bsplines.py
├── exm_flow_model.py
├── exm_geometry.py
├── exm_qt_app.py
├── exm_qt_app.ui
├── exm_qt_vis.py
├── exm_qt_vis.ui
├── exm_stress_2d.py
├── exm_stress_2d_export.py
├── exm_stress_2d_materials.py
├── exm_stress_2d_pyvtk.py
├── exm_stress_2d_qt.py
├── exm_stress_2d_qt.ui
├── exm_structured_mesh.py
├── exm_structured_mesh_3d.py
├── exm_structured_mesh_vtk.py
├── exm_temp_2d_markers.py
├── exm_temp_2d_splines_arcs.py
├── exm_tet_mesh.py
├── exm_tet_mesh_vtk.py
├── exm_tutorial_1.py
├── exm_tutorial_2.py
├── exn_bar2g.py
├── exn_bar2m.py
├── exn_beam2.py
├── exn_beam2_b.py
├── experimental
│ ├── .vscode
│ │ └── settings.json
│ ├── exed1.py
│ ├── exed1.ui
│ ├── exint1.py
│ ├── exm11.py
│ ├── exm11_mpl.py
│ ├── exm12.ipynb
│ ├── exm12.py
│ ├── exm12_mpl.py
│ ├── exm14_vtk.py
│ ├── exm1_mpl_edit.py
│ ├── exs6.py
│ ├── exui1.py
│ ├── gmsh_api.py
│ ├── gmsh_api2.py
│ ├── path_int.py
│ ├── plot_tst.py
│ ├── point_in_geom.py
│ ├── prim3d.py
│ ├── qt1.py
│ ├── qt2.py
│ └── tri_mesh.py
├── exs_bar2.py
├── exs_bar2_la.py
├── exs_bar2_lb.py
├── exs_beam1.ipynb
├── exs_beam1.py
├── exs_beam2.ipynb
├── exs_beam2.py
├── exs_beambar2.py
├── exs_flw_diff2.py
├── exs_flw_temp1.py
├── exs_flw_temp2.py
├── exs_spring.py
├── exv1.py
├── exv2.py
├── exv3.py
├── exv4.m
├── exv4.mat
├── exv4.py
├── exv5.py
├── exvis_beam_soli8.py
├── gmsh-api
│ ├── exgm1.py
│ ├── exgm2.py
│ ├── exgm3.py
│ └── exgm4.py
└── obsolete
│ ├── extri1.py
│ └── extri2.py
├── gen_output_dict.py
├── pyproject.toml
├── reports
├── manual-mesh-module.pdf
└── manual.pdf
├── resources
└── resources.qrc
├── src
├── __init__.py
└── calfem
│ ├── __init__.py
│ ├── _export.py
│ ├── classes_qt4.py
│ ├── classes_wx.py
│ ├── core.py
│ ├── core_compat.py
│ ├── editor.py
│ ├── editor.ui
│ ├── editor_resources.py
│ ├── editor_scene.py
│ ├── editor_ui.py
│ ├── experimental.py
│ ├── geometry.py
│ ├── intvis.py
│ ├── mesh.py
│ ├── misc.py
│ ├── qt5.py
│ ├── shapes.py
│ ├── solver.py
│ ├── ui.py
│ ├── utils.py
│ ├── vedo_utils.py
│ ├── vis.py
│ ├── vis_mpl.py
│ ├── vis_vedo.py
│ ├── vis_vedo_utils.py
│ └── vis_vtk.py
├── test_calfem.py
└── tests
└── __init__.py
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | *.pyc
3 |
4 | *.msh
5 |
6 | *.geo
7 |
8 | *.bak
9 |
10 | docs/build
11 | docs/pycalfem
12 |
13 | venv-calfem
14 |
15 | .spyproject/
16 |
17 | calfem/shapes - kopia.py
18 |
19 | calfem_python.egg-info/*
20 | calfem_python_small.egg-info/*
21 |
22 | .vscode/launch.json
23 | *.project
24 | .pydevproject
25 | *.prefs
26 | calfem-python.pyproj
27 | *.suo
28 | calfem-python.sln
29 | build/
30 | calfem_python.egg-info/
31 | dist/
32 | *.xml
33 | *.iml
34 | .idea/
35 | .vscode/settings.json
36 | examples/.ipynb_checkpoints/*
37 | # .vscode/settings.json
38 | calfem/.ipynb_checkpoints/*
39 | exm6.vtk
40 |
41 | # new notebook examples
42 | docs/source/examples/.ipynb_checkpoints/
43 | .DS_Store
44 | *.lock
45 | *.log
46 | *.log
47 | *.log
48 | .pdm-python
49 | test_examples_output.log
50 | *.log
51 | test_examples.log
52 |
--------------------------------------------------------------------------------
/.pdm-python:
--------------------------------------------------------------------------------
1 | C:/Users/jonas/miniconda3/envs/calfem-dev/python.EXE
--------------------------------------------------------------------------------
/.readthedocs.yaml:
--------------------------------------------------------------------------------
1 | # Read the Docs configuration file for Sphinx projects
2 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
3 |
4 | # Required
5 | version: 2
6 |
7 | # Set the OS, Python version and other tools you might need
8 | build:
9 | os: ubuntu-22.04
10 | tools:
11 | python: "3.12"
12 | # You can also specify other tool versions:
13 | # nodejs: "20"
14 | # rust: "1.70"
15 | # golang: "1.20"
16 |
17 | # Build documentation in the "docs/" directory with Sphinx
18 | sphinx:
19 | configuration: docs/source/conf.py
20 | # You can configure Sphinx to use a different builder, for instance use the dirhtml builder for simpler URLs
21 | # builder: "dirhtml"
22 | # Fail on all warnings to avoid broken references
23 | # fail_on_warning: true
24 |
25 | # Optionally build your docs in additional formats such as PDF and ePub
26 | # formats:
27 | # - pdf
28 | # - epub
29 |
30 | # Optional but recommended, declare the Python requirements required
31 | # to build your documentation
32 | # See https://docs.readthedocs.io/en/stable/guides/reproducible-builds.html
33 | python:
34 | install:
35 | - requirements: docs/requirements.txt
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Division of Structural Mechanics
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2018-2021 Division of Structural Mechanics
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/MANIFEST.in:
--------------------------------------------------------------------------------
1 | include *.md
2 | include *.rst
3 | recursive-include examples *.py
4 | graft examples
5 | global-exclude *.py[co]
6 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # CALFEM for Python
2 |
3 | ## Documentation
4 |
5 | [https://calfem-for-python.readthedocs.io/en/latest/](https://calfem-for-python.readthedocs.io/en/latest/)
6 |
7 | ## Manuals
8 |
9 | Original manual: [manual.pdf](https://github.com/CALFEM/calfem-python/tree/master/reports/manual.pdf)
10 |
11 | Manual for with improved mesh: [manual-mesh-module.pdf](https://github.com/CALFEM/calfem-python/tree/master/reports/manual-mesh-module.pdf)
12 |
13 | ## Background
14 |
15 | The computer program CALFEM is written for the software MATLAB and is an interactive tool for learning the finite element method. CALFEM is an abbreviation
16 | of ”Computer Aided Learning of the Finite Element Method” and been developed by the Division of Structural Mechanics at Lund University since the late 70’s.
17 |
18 | ## Why CALFEM for Python?
19 |
20 | While both the MATLAB and Python versions of CALFEM are open-source (MIT Licensed), the key difference lies in the environments they operate in. MATLAB is not open-source and requires expensive licenses (for commercial use), which can be a barrier for many users. In contrast, Python is a free, open-source programming language, making CALFEM for Python more accessible and cost-effective for a broader audience, including those in academic, personal, or commercial settings.
21 |
22 | CALFEM for Python is released under the MIT license, which enables its use in open-source as well as commercial projects.
23 |
24 | ## Installation
25 |
26 | Install CALFEM for python using
27 | `pip install calfem-python`
28 |
29 | ## Dependencies
30 |
31 | Mesh Generation Software: GMSH.
32 | Install GMSH [here](http://gmsh.info/) and add to the PATH of your file or instead add contents of GMSH to the file folder.
33 |
34 | ## References
35 |
36 | * Forsman, K, 2017. VisCon: Ett visualiseringsverktyg för tvådimensionell konsolidering i undervisningssammanhang - http://www.byggmek.lth.se/fileadmin/byggnadsmekanik/publications/tvsm5000/web5225.pdf
37 |
38 | * Edholm, A., 2013. Meshing and visualisation routines in the Python version of CALFEM. - http://www.byggmek.lth.se/fileadmin/byggnadsmekanik/publications/tvsm5000/web5187.pdf
39 |
40 | * Ottosson, A., 2010. Implementation of CALFEM for Python - http://www.byggmek.lth.se/fileadmin/byggnadsmekanik/publications/tvsm5000/web5167.pdf
41 |
42 | * Eriksson, K, 2021. CALFEM Geometry Editor - An interactive geometry editor for CALFEM
43 |
44 | * Åmand, A, 2022. Development of visualisation functions for CALFEM for Python
45 |
46 |
47 |
--------------------------------------------------------------------------------
/README.rst:
--------------------------------------------------------------------------------
1 | The computer program CALFEM is written for the software MATLAB and is an interactive tool for learning the finite element method. CALFEM is an abbreviation
2 | of ”Computer Aided Learning of the Finite Element Method” and been developed by the Division of Structural Mechanics at Lund University since the late 70’s.
3 |
4 | Unlike MATLAB, which have expensive licenses, Python is free to use and distribute both for personal and commercial use. This is the python version of CALFEM for scientific purposes/research.
5 |
--------------------------------------------------------------------------------
/archive/setup-org.py:
--------------------------------------------------------------------------------
1 | """A setuptools based setup module.
2 |
3 | See:
4 | https://github.com/CALFEM/calfem-python
5 | """
6 |
7 | # Always prefer setuptools over distutils
8 | from setuptools import setup, find_packages
9 | # To use a consistent encoding
10 | from codecs import open
11 | from os import path
12 | import os, glob, sys
13 |
14 | here = path.abspath(path.dirname(__file__))
15 |
16 | # Get the long description from the README file
17 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
18 | long_description = f.read()
19 |
20 | def gen_data_files(*dirs):
21 | results = []
22 |
23 | for src_dir in dirs:
24 | for root,dirs,files in os.walk(src_dir):
25 | results.append((root, map(lambda f:root + "/" + f, files)))
26 | return results
27 |
28 | setup(
29 | name='calfem-python',
30 |
31 | # Versions should comply with PEP440. For a discussion on single-sourcing
32 | # the version across setup.py and the project code, see
33 | # https://packaging.python.org/en/latest/single_source_version.html
34 |
35 | version='3.6.4',
36 |
37 | description='CALFEM for Python',
38 | long_description='The computer program CALFEM is written for the software MATLAB and is an interactive tool for learning the finite element method. CALFEM is an abbreviation of "Computer Aided Learning of the Finite Element Method" and been developed by the Division of Structural Mechanics at Lund University since the late 70s.',
39 |
40 | # The project's main homepage.
41 | url='https://github.com/CALFEM/calfem-python',
42 |
43 | # Author details
44 | author='Jonas Lindemann, et al',
45 | author_email='jonas.lindemann@byggmek.lth.se',
46 |
47 | # Choose your license
48 | license='MIT',
49 |
50 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
51 | classifiers=[
52 | # How mature is this project? Common values are
53 | # 3 - Alpha
54 | # 4 - Beta
55 | # 5 - Production/Stable
56 | 'Development Status :: 4 - Beta',
57 |
58 | # Indicate who your project is intended for
59 | 'Intended Audience :: Developers',
60 | 'Topic :: Software Development :: Build Tools',
61 |
62 | # Pick your license as you wish (should match "license" above)
63 | 'License :: OSI Approved :: MIT License',
64 |
65 | # Specify the Python versions you support here. In particular, ensure
66 | # that you indicate whether you support Python 2, Python 3 or both.
67 | 'Programming Language :: Python :: 3',
68 | 'Programming Language :: Python :: 3.7',
69 | 'Programming Language :: Python :: 3.8',
70 | 'Programming Language :: Python :: 3.9',
71 | 'Programming Language :: Python :: 3.10',
72 | 'Programming Language :: Python :: 3.11',
73 | ],
74 |
75 | # What does your project relate to?
76 | keywords='finite element, math, numerics',
77 |
78 | # You can just specify the packages manually here if your project is
79 | # simple. Or you can use find_packages().
80 | #packages=find_packages(exclude=['contrib', 'docs', 'tests']),
81 | #packages=find_packages(exclude=['docs', 'old', 'examples', 'examplegeo']),
82 | packages=['calfem',],
83 |
84 | # Alternatively, if you want to distribute just a my_module.py, uncomment
85 | # this:
86 | # py_modules=["my_module"],
87 |
88 | # List run-time dependencies here. These will be installed by pip when
89 | # your project is installed. For an analysis of "install_requires" vs pip's
90 | # requirements files see:
91 | # https://packaging.python.org/en/latest/requirements.html
92 | install_requires=['numpy', 'visvis', 'pyvtk', 'matplotlib', 'scipy', 'gmsh', 'qtpy', 'vedo', 'tabulate'],
93 | include_package_data=True
94 | #package_data={'calfem': ['examples/*']}
95 |
96 | #data_files=gen_data_files("examples", "doc")
97 |
98 | #package_data={
99 | # 'calfem': ['examples/*.py', 'examples/*.ui']
100 | #}
101 |
102 | # List additional groups of dependencies here (e.g. development
103 | # dependencies). You can install these using the following syntax,
104 | # for example:
105 | # $ pip install -e .[dev,test]
106 | #extras_require={
107 | # 'dev': ['check-manifest'],
108 | # 'test': ['coverage'],
109 | #},
110 |
111 | # If there are data files included in your packages that need to be
112 | # installed, specify them here. If using Python 2.6 or less, then these
113 | # have to be included in MANIFEST.in as well.
114 | )
115 |
--------------------------------------------------------------------------------
/archive/setup-template.py:
--------------------------------------------------------------------------------
1 | """A setuptools based setup module.
2 |
3 | See:
4 | https://github.com/CALFEM/calfem-python
5 | """
6 |
7 | # Always prefer setuptools over distutils
8 | from setuptools import setup, find_packages
9 | # To use a consistent encoding
10 | from codecs import open
11 | from os import path
12 | import os, glob, sys
13 |
14 | here = path.abspath(path.dirname(__file__))
15 |
16 | # Get the long description from the README file
17 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
18 | long_description = f.read()
19 |
20 | def gen_data_files(*dirs):
21 | results = []
22 |
23 | for src_dir in dirs:
24 | for root,dirs,files in os.walk(src_dir):
25 | results.append((root, map(lambda f:root + "/" + f, files)))
26 | return results
27 |
28 | setup(
29 | name='{package_name}',
30 |
31 | # Versions should comply with PEP440. For a discussion on single-sourcing
32 | # the version across setup.py and the project code, see
33 | # https://packaging.python.org/en/latest/single_source_version.html
34 |
35 | version='{package_version}',
36 |
37 | description='CALFEM for Python',
38 | long_description='The computer program CALFEM is written for the software MATLAB and is an interactive tool for learning the finite element method. CALFEM is an abbreviation of "Computer Aided Learning of the Finite Element Method" and been developed by the Division of Structural Mechanics at Lund University since the late 70s.',
39 |
40 | # The project's main homepage.
41 | url='https://github.com/CALFEM/calfem-python',
42 |
43 | # Author details
44 | author='Jonas Lindemann, et al',
45 | author_email='jonas.lindemann@lunarc.lu.se',
46 |
47 | # Choose your license
48 | license='MIT',
49 |
50 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
51 | classifiers=[
52 | # How mature is this project? Common values are
53 | # 3 - Alpha
54 | # 4 - Beta
55 | # 5 - Production/Stable
56 | 'Development Status :: 4 - Beta',
57 |
58 | # Indicate who your project is intended for
59 | 'Intended Audience :: Developers',
60 | 'Topic :: Software Development :: Build Tools',
61 |
62 | # Pick your license as you wish (should match "license" above)
63 | 'License :: OSI Approved :: MIT License',
64 |
65 | # Specify the Python versions you support here. In particular, ensure
66 | # that you indicate whether you support Python 2, Python 3 or both.
67 | 'Programming Language :: Python :: 3',
68 | 'Programming Language :: Python :: 3.7',
69 | 'Programming Language :: Python :: 3.8',
70 | 'Programming Language :: Python :: 3.9',
71 | 'Programming Language :: Python :: 3.10',
72 | 'Programming Language :: Python :: 3.11',
73 | 'Programming Language :: Python :: 3.12',
74 | ],
75 |
76 | # What does your project relate to?
77 | keywords='finite element, math, numerics',
78 |
79 | # You can just specify the packages manually here if your project is
80 | # simple. Or you can use find_packages().
81 | #packages=find_packages(exclude=['contrib', 'docs', 'tests']),
82 | #packages=find_packages(exclude=['docs', 'old', 'examples', 'examplegeo']),
83 | packages=['calfem',],
84 |
85 | # Alternatively, if you want to distribute just a my_module.py, uncomment
86 | # this:
87 | # py_modules=["my_module"],
88 |
89 | # List run-time dependencies here. These will be installed by pip when
90 | # your project is installed. For an analysis of "install_requires" vs pip's
91 | # requirements files see:
92 | # https://packaging.python.org/en/latest/requirements.html
93 | install_requires=[{package_depends}],
94 | include_package_data=True
95 |
96 | #data_files=gen_data_files("examples", "doc")
97 |
98 | )
99 |
--------------------------------------------------------------------------------
/archive/setup.py:
--------------------------------------------------------------------------------
1 | """A setuptools based setup module.
2 |
3 | See:
4 | https://github.com/CALFEM/calfem-python
5 | """
6 |
7 | # Always prefer setuptools over distutils
8 | from setuptools import setup, find_packages
9 | # To use a consistent encoding
10 | from codecs import open
11 | from os import path
12 | import os, glob, sys
13 |
14 | here = path.abspath(path.dirname(__file__))
15 |
16 | # Get the long description from the README file
17 | with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
18 | long_description = f.read()
19 |
20 | def gen_data_files(*dirs):
21 | results = []
22 |
23 | for src_dir in dirs:
24 | for root,dirs,files in os.walk(src_dir):
25 | results.append((root, map(lambda f:root + "/" + f, files)))
26 | return results
27 |
28 | setup(
29 | name='calfem-python-small',
30 |
31 | # Versions should comply with PEP440. For a discussion on single-sourcing
32 | # the version across setup.py and the project code, see
33 | # https://packaging.python.org/en/latest/single_source_version.html
34 |
35 | version='3.6.6',
36 |
37 | description='CALFEM for Python',
38 | long_description='The computer program CALFEM is written for the software MATLAB and is an interactive tool for learning the finite element method. CALFEM is an abbreviation of "Computer Aided Learning of the Finite Element Method" and been developed by the Division of Structural Mechanics at Lund University since the late 70s.',
39 |
40 | # The project's main homepage.
41 | url='https://github.com/CALFEM/calfem-python',
42 |
43 | # Author details
44 | author='Jonas Lindemann, et al',
45 | author_email='jonas.lindemann@lunarc.lu.se',
46 |
47 | # Choose your license
48 | license='MIT',
49 |
50 | # See https://pypi.python.org/pypi?%3Aaction=list_classifiers
51 | classifiers=[
52 | # How mature is this project? Common values are
53 | # 3 - Alpha
54 | # 4 - Beta
55 | # 5 - Production/Stable
56 | 'Development Status :: 4 - Beta',
57 |
58 | # Indicate who your project is intended for
59 | 'Intended Audience :: Developers',
60 | 'Topic :: Software Development :: Build Tools',
61 |
62 | # Pick your license as you wish (should match "license" above)
63 | 'License :: OSI Approved :: MIT License',
64 |
65 | # Specify the Python versions you support here. In particular, ensure
66 | # that you indicate whether you support Python 2, Python 3 or both.
67 | 'Programming Language :: Python :: 3',
68 | 'Programming Language :: Python :: 3.7',
69 | 'Programming Language :: Python :: 3.8',
70 | 'Programming Language :: Python :: 3.9',
71 | 'Programming Language :: Python :: 3.10',
72 | 'Programming Language :: Python :: 3.11',
73 | 'Programming Language :: Python :: 3.12',
74 | ],
75 |
76 | # What does your project relate to?
77 | keywords='finite element, math, numerics',
78 |
79 | # You can just specify the packages manually here if your project is
80 | # simple. Or you can use find_packages().
81 | #packages=find_packages(exclude=['contrib', 'docs', 'tests']),
82 | #packages=find_packages(exclude=['docs', 'old', 'examples', 'examplegeo']),
83 | packages=['calfem',],
84 |
85 | # Alternatively, if you want to distribute just a my_module.py, uncomment
86 | # this:
87 | # py_modules=["my_module"],
88 |
89 | # List run-time dependencies here. These will be installed by pip when
90 | # your project is installed. For an analysis of "install_requires" vs pip's
91 | # requirements files see:
92 | # https://packaging.python.org/en/latest/requirements.html
93 | install_requires=['numpy', 'visvis', 'matplotlib', 'scipy', 'gmsh', 'tabulate'],
94 | include_package_data=True
95 |
96 | #data_files=gen_data_files("examples", "doc")
97 |
98 | )
99 |
--------------------------------------------------------------------------------
/build-package.py:
--------------------------------------------------------------------------------
1 |
2 | import os, sys
3 |
4 | def update_setup(package_name, package_version, package_deps):
5 |
6 | with open("setup-template.py", "r") as f:
7 | setup_template = f.read()
8 |
9 | with open("setup.py", "w") as f:
10 | f.write(setup_template.format(package_name=package_name, package_version=package_version, package_depends=package_deps))
11 |
12 | def build_package():
13 | os.system("C:\Users\Miniconda3\envs\calfem-dev\python.exe -m build --wheel")
14 |
15 | if __name__ == "__main__":
16 |
17 | package_version = "3.6.6"
18 |
19 | update_setup("calfem-python", package_version, "'numpy', 'visvis', 'pyvtk', 'matplotlib', 'scipy', 'gmsh', 'qtpy', 'vedo', 'tabulate'")
20 |
21 | build_package()
22 |
23 | update_setup("calfem-python-small", package_version, "'numpy', 'visvis', 'matplotlib', 'scipy', 'gmsh', 'tabulate'")
24 |
25 | build_package()
26 |
27 |
--------------------------------------------------------------------------------
/docs/make.bat:
--------------------------------------------------------------------------------
1 | @ECHO OFF
2 |
3 | pushd %~dp0
4 |
5 | REM Command file for Sphinx documentation
6 |
7 | rem if "%SPHINXBUILD%" == "" (
8 | set SPHINXBUILD=sphinx-build
9 | rem )
10 | set SOURCEDIR=source
11 | set BUILDDIR=build
12 |
13 | if "%1" == "" goto help
14 |
15 | %SPHINXBUILD% >NUL 2>NUL
16 | if errorlevel 9009 (
17 | echo.
18 | echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
19 | echo.installed, then set the SPHINXBUILD environment variable to point
20 | echo.to the full path of the 'sphinx-build' executable. Alternatively you
21 | echo.may add the Sphinx directory to PATH.
22 | echo.
23 | echo.If you don't have Sphinx installed, grab it from
24 | echo.https://www.sphinx-doc.org/
25 | exit /b 1
26 | )
27 |
28 | %SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
29 | goto end
30 |
31 | :help
32 | %SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
33 |
34 | :end
35 | popd
36 |
--------------------------------------------------------------------------------
/docs/requirements.txt:
--------------------------------------------------------------------------------
1 | visvis
2 | PyQt5
3 | pyvtk
4 | calfem-python
5 | ipython_genutils==0.1.0
6 | sphinx==6.1
7 | nbsphinx==0.9.3
8 | sphinx-material
9 |
--------------------------------------------------------------------------------
/docs/source/calfem.logo.bw.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/docs/source/calfem_examples.rst:
--------------------------------------------------------------------------------
1 | Using CALFEM for Python
2 | =======================
3 |
4 | What is CALFEM?
5 | ---------------
6 |
7 | CALFEM is an interactive computer program for teaching the finite element method (FEM). The name CALFEM is an abbreviation of "Computer Aided Learning of the Finite Element Method". The program can be used for different types of structural mechanics problems and field problems.
8 |
9 | CALFEM, the program and its built-in philosophy, have been developed at the Division of Structural Mechanics, Lund University, starting in the late 70's. Many coworkers, former and present, have been engaged in the development at different stages.
10 |
11 | What is CALFEM for Python?
12 | --------------------------
13 | * Subset of CALFEM routines implemented in Python
14 | * Using NumPy for matrices
15 | * Additional mesh generation routines supporting Triangle and GMSH
16 | * Plotting with Matplotlib and visvis
17 |
18 | CALFEM Python modules
19 | ---------------------
20 |
21 | * **calfem.core**
22 |
23 | * Element routines
24 | * System routines
25 | * **calfem.utils**
26 |
27 | * I/O routines
28 | * Misc. routines
29 | * **calfem.geometry**
30 |
31 | * Routines for defining problem geometry used for input in mesh generation
32 | * **calfem.mesh**
33 |
34 | * Mesh generation routines
35 | * **calfem.vis/calfem.vis_mpl**
36 |
37 | * Routines for visualising geometry, meshes and results.
38 |
39 | Examples
40 | --------
41 | The example codes show what CALFEM can do for you. The examples are divided into two:
42 |
43 | - Numerical examples
44 |
45 | - Mesh examples
46 |
47 | The next is tutorial on using Calfem for Python for numerical finite element, i.e., solving FEM equation to obtain nodal displacements given loading forces and
48 | stiffness matrix. The example can be found in `examples` directories both on
49 | calfem-python root directory (for .py files) and docs directory (for .ipynb files).
50 |
--------------------------------------------------------------------------------
/docs/source/calfem_reference.rst:
--------------------------------------------------------------------------------
1 | Function reference
2 | ==================
3 |
4 | Core functions
5 | --------------
6 |
7 | .. automodule:: calfem.core
8 | :members:
9 |
10 | Geometry functions
11 | ------------------
12 |
13 | .. automodule:: calfem.geometry
14 | :members:
15 |
16 | Mesh functions
17 | --------------
18 |
19 | .. automodule:: calfem.mesh
20 | :members:
21 |
22 | User interface functions
23 | ------------------------
24 |
25 | .. automodule:: calfem.ui
26 | :members:
27 |
28 | Utility functions
29 | -----------------
30 |
31 | .. automodule:: calfem.utils
32 | :members:
33 |
34 | Visualisation functions (Matplotlib)
35 | ------------------------------------
36 |
37 | .. automodule:: calfem.vis_mpl
38 | :members:
39 |
40 | Visualisation functions (VisVis)
41 | --------------------------------
42 |
43 | .. automodule:: calfem.vis
44 | :members:
45 |
46 | Interactive Geometry Editor
47 | ---------------------------
48 |
49 | .. automodule:: calfem.editor
50 | :members:
51 |
--------------------------------------------------------------------------------
/docs/source/developer.rst:
--------------------------------------------------------------------------------
1 | Developing CALFEM for Python
2 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
3 |
4 | Creating an environment for development
5 | ---------------------------------------
6 |
7 | It could be benficial to create an dedicated environment for development. This can be easily created in the Anaconda distribution.::
8 |
9 | conda create -n calfem-dev python=3.9
10 | conda activate calfem-dev
11 |
12 | Installing dependencies
13 | -----------------------
14 |
15 | To develop for CALFEM for Python you will need to install the required dependencies first. The easiest way to do this is to install the pip version of CALFEM::
16 |
17 | pip install calfem-python
18 |
19 | Creating a fork in GitHub
20 | -------------------------
21 |
22 | To be able to submit code changes and addition it is a good idea to create a fork on GitHub. A fork is your own version of CALFEM for Python in which you can track changes. From the fork you can also easily create a pull request, that is a suggested change that you can submit to CALFEM for Python.
23 |
24 | Please see
25 |
26 | https://reflectoring.io/github-fork-and-pull/
27 |
28 | for more information on how to create and manage forks.
29 |
30 | Checking out code from github
31 | -----------------------------
32 |
33 | It is also possible to check out a local version of the code from the command line. The master or develop branches can be checkout with the following procedures:
34 |
35 | Cloning the master branch on your local computer.::
36 |
37 | git clone https://github.com/CALFEM/calfem-python.git
38 |
39 | Cloning the develop branch on your local computer.::
40 |
41 | git clone https://github.com/CALFEM/calfem-python.git
42 | git checkout develop
43 |
44 | It is also possible to use the command line tools to clone your github fork:
45 |
46 | git clone https://github.com/USERNAME/calfem-python.git
47 |
48 |
49 | Using GitHub Desktop to manage your code
50 | ----------------------------------------
51 |
52 | GitHub Desktop is a graphical client for GitHub that makes the procedure working with git-repos much more easy. More information on how to use GitHub Desktop can be found here:
53 |
54 | https://desktop.github.com/
55 |
56 | https://docs.github.com/en/desktop
57 |
58 |
59 | Modifying the Python search PATH
60 | --------------------------------
61 |
62 | To work on the checked out source directory, set the PYTHONPATH environment variable to the root of the source directory.
63 |
64 | On Windows::
65 |
66 | set PYTHONPATH=C:\[Path to source directory]
67 |
68 | On other platforms::
69 |
70 | export PYTHONPATH=[Path to source directory]
71 |
72 | Guidelines
73 | ----------
74 |
75 | If you want to develop standalone element routines for CALFEM it is probarbly a good idea to develop them standalone and then submit a change request for inclusion in the calfem.extension module.
76 |
77 | Element routines should be named according to the following rule:
78 |
79 | [name][1|2|3][e|s]
80 |
81 | Where 1,2 and 3 indicates element dimensions. e - denotes that the routine returns element stiffness matrix and or force vector. s - denotes that the routines returns element forces given element nodal values.
82 |
83 | Please look at existing routines to familiar yourself with how they are constructued.
84 |
85 | All routines should have documentation strings describing input and output parameters. Code comments describing the general flow should be added to the function at relevant positions.
86 |
87 | Submit a Pull request
88 | ---------------------
89 |
90 | If you want your changes to be included in future releases of CALFEM please create a pull request against GitHub. More information on this can be found here:
91 |
92 | https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request
93 |
94 |
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/docs/source/examples/cfeditor.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 |
19 |
40 |
41 |
42 |
43 | Open...
44 |
45 |
46 |
47 |
48 | Save
49 |
50 |
51 |
52 |
53 | Save as...
54 |
55 |
56 |
57 |
58 | Exit
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/docs/source/examples/exmqt1.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 806
10 | 559
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 0
23 | 0
24 |
25 |
26 |
27 |
28 | 16777215
29 | 50
30 |
31 |
32 |
33 | QFrame::StyledPanel
34 |
35 |
36 | QFrame::Raised
37 |
38 |
39 |
-
40 |
41 |
42 | Execute
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Qt::Horizontal
50 |
51 |
52 |
53 | 40
54 | 20
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | -
63 |
64 |
65 |
66 |
67 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/source/examples/exmqt6.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 806
10 | 559
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 0
23 | 0
24 |
25 |
26 |
27 |
28 | 16777215
29 | 50
30 |
31 |
32 |
33 | QFrame::StyledPanel
34 |
35 |
36 | QFrame::Raised
37 |
38 |
39 |
-
40 |
41 |
42 | Execute
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Qt::Horizontal
50 |
51 |
52 |
53 | 40
54 | 20
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | -
63 |
64 |
65 |
66 |
67 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/docs/source/exs1.rst:
--------------------------------------------------------------------------------
1 | Example: Connected springs
2 | -------------------------------------
3 |
4 | This example is from the CALFEM manual (exs1.py).
5 |
6 | **Purpose:**
7 |
8 | Show the basic steps in a finite element calculation.
9 |
10 | **Description:**
11 |
12 | The general procedure in linear finite element calculations is carried out for a
13 | simple structure. The steps are:
14 |
15 | * define the model
16 | * generate element matrices
17 | * assemble element matrices into the global system of equations
18 | * solve the global system of equations
19 | * evaluate element forces
20 |
21 | Consider the system of three linear elastic springs, and the corresponding
22 | finite element model. The system of springs is fixed in its ends and loaded by a
23 | single load F. To make it convenience, we follow notation in "Fundamentals of Finite Element Analysis" by David Hutton, where square is symbol for nodes, circle is for element, and U is for (global) nodal displacement. Capital letter shows global variables while small letter follows local variables.
24 |
25 | .. image:: images/exs1-1-rev1.png
26 |
27 | We begin our FEM computation by importing required modules
28 |
29 | .. literalinclude:: ../../examples/exs_spring.py
30 | :lines: 16-17
31 |
32 | The computation is initialized by defining the topology matrix Edof, containing
33 | element numbers and global element degrees of freedom. All input to CALFEM is NumPy arrays. Topology is defined by index 1, i.e., the first row represents the first element bounded by node 1 and node 2. Hence we write
34 |
35 | .. literalinclude:: ../../examples/exs_spring.py
36 | :lines: 20-24
37 |
38 | the initial global stiffness matrix `K` (3x3) and load force `f` containing zeros,
39 |
40 | .. literalinclude:: ../../examples/exs_spring.py
41 | :lines: 27-28
42 |
43 | Element stiffness matrices are generated by the function spring1e. The element
44 | property `ep` for the springs contains the spring stiffnesses k and 2k
45 | respectively, where k = 1500.
46 |
47 | .. literalinclude:: ../../examples/exs_spring.py
48 | :lines: 30-43
49 |
50 | The output is printed as follows::
51 |
52 | Stiffness matrix K:
53 | [[ 3000. -3000. 0.]
54 | [-3000. 7500. -4500.]
55 | [ 0. -4500. 4500.]]
56 |
57 | and the load/force vector f (3x1) with the load F = 100 in position 2 (Note that Python indexes from 0, hence f[1] corresponds to edof 2).
58 |
59 | .. literalinclude:: ../../examples/exs_spring.py
60 | :lines: 46
61 |
62 | The element stiffness matrices are assembled into the global stiffness matrix K
63 | according to the topology. `bc` is an array of prescribed degrees of freedom. Values to be specified are specified in a separate array. If all values are 0, they don't have to be specified.
64 | The global system of equations is solved considering the boundary conditions
65 | given in bc.
66 |
67 | .. literalinclude:: ../../examples/exs_spring.py
68 | :lines: 49-56
69 |
70 | output: ::
71 |
72 | Displacements a:
73 | [[0. ]
74 | [0.01333333]
75 | [0. ]]
76 | Reaction forces Q:
77 | [[-40.]
78 | [ 0.]
79 | [-60.]]
80 |
81 | Element forces are evaluated from the element displacements. These are obtained
82 | from the global displacements `a` using the function extract.
83 |
84 | .. literalinclude:: ../../examples/exs_spring.py
85 | :lines: 59-61
86 |
87 | The spring element forces at each element are evaluated using the function spring1s.
88 |
89 | .. literalinclude:: ../../examples/exs_spring.py
90 | :lines: 68-70
91 |
92 | Output: ::
93 |
94 | Element forces N:
95 | N1 = 40.0
96 | N2 = -20.0
97 | N3 = -40.0
98 |
99 |
--------------------------------------------------------------------------------
/docs/source/images/SVG/Rityta 1.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/source/images/bars1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/bars1.png
--------------------------------------------------------------------------------
/docs/source/images/bars2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/bars2.png
--------------------------------------------------------------------------------
/docs/source/images/bars3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/bars3.png
--------------------------------------------------------------------------------
/docs/source/images/calfem.logo.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/calfem.logo.ai
--------------------------------------------------------------------------------
/docs/source/images/calfem.logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/calfem.logo.png
--------------------------------------------------------------------------------
/docs/source/images/calfem.logo.sw.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/docs/source/images/exm0_2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/exm0_2.png
--------------------------------------------------------------------------------
/docs/source/images/exs1-1-rev1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/exs1-1-rev1.png
--------------------------------------------------------------------------------
/docs/source/images/exs1-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/exs1-1.png
--------------------------------------------------------------------------------
/docs/source/images/exs2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/exs2.png
--------------------------------------------------------------------------------
/docs/source/images/frame_and_bars.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/frame_and_bars.png
--------------------------------------------------------------------------------
/docs/source/images/mesh1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/mesh1.png
--------------------------------------------------------------------------------
/docs/source/images/mesh2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/mesh2.png
--------------------------------------------------------------------------------
/docs/source/images/mesh3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/mesh3.png
--------------------------------------------------------------------------------
/docs/source/images/tut2-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/docs/source/images/tut2-1.png
--------------------------------------------------------------------------------
/docs/source/index.rst:
--------------------------------------------------------------------------------
1 | .. CALFEM for Python documentation master file, created by
2 | sphinx-quickstart on Mon May 30 23:34:38 2016.
3 | You can adapt this file completely to your liking, but it should at least
4 | contain the root `toctree` directive.
5 |
6 | .. image:: images/calfem.logo.png
7 | :scale: 20 %
8 |
9 | CALFEM for Python - Documentation
10 | =================================
11 |
12 | Welcome to the documentation for CALFEM for Python. On this page you will find examples of how to use CALFEM for Python as well as reference documentation for the different modules contained in the CALFEM for Python distribution. This is not a replacement for the CALFEM Manual, but contain information on how to use CALFEM in a Python context.
13 |
14 | Contents:
15 | ---------
16 |
17 | .. toctree::
18 | :maxdepth: 1
19 | :caption: Installation
20 |
21 | installation
22 |
23 | .. toctree::
24 | :maxdepth: 2
25 | :caption: Tutorial
26 |
27 | calfem_examples
28 | exs1
29 | examples/exs2
30 | examples/exs3
31 | examples/exs4
32 | examples/exs7
33 | calfem_mesh_guide
34 | examples/exm1
35 | examples/exm2
36 | examples/exm3
37 | examples/exm6
38 | examples/exm10
39 |
40 | .. toctree::
41 | :maxdepth: 1
42 | :caption: Developing
43 |
44 | developer
45 |
46 | .. toctree::
47 | :maxdepth: 1
48 | :caption: Function Reference
49 |
50 | calfem_reference
51 |
52 |
53 | ==================
54 | Indices and tables
55 | ==================
56 |
57 | * :ref:`genindex`
58 | * :ref:`modindex`
59 | * :ref:`search`
60 |
61 |
--------------------------------------------------------------------------------
/docs/source/installation.rst:
--------------------------------------------------------------------------------
1 | Installation instructions
2 | ^^^^^^^^^^^^^^^^^^^^^^^^^
3 |
4 | The simplest way to install CALFEM for Python is via pip.
5 | This procedure will ensure that all required dependencies are fulfilled.
6 |
7 | This can be achieved by executing the following command::
8 |
9 | pip install calfem-python
10 |
11 | or::
12 |
13 | sudo pip install calfem-python
14 |
15 | to install system-wide (not recommended if your system used a lot of python dependencies)::
16 |
17 | pip install -u calfem-python
18 |
19 | to install just for your own user. You can use the argument `--user` which is
20 | same as `-u`. If you want to specify your Python version, use the command like
21 | the following::
22 |
23 | python3.9 -m pip install --user calfem-python
24 |
25 | where python3.9 is the Python version you want to install CALFEM for
26 | Python. Change this command with your preferable version. This last command is
27 | the preferred one according to the Python community.
28 |
29 | Installing in a Anaconda environment
30 | ------------------------------------
31 |
32 | If you don't want to install all packages directly in the base Anaconda environment you could create a new enviroment for CALFEM::
33 |
34 | conda create -n calfem-dev python=3.9
35 | conda activate calfem-dev
36 |
37 | Now we can install CALFEM for Python and its dependencies directly into this environment using Pip.::
38 |
39 | pip install calfem-python
40 |
41 |
42 |
--------------------------------------------------------------------------------
/examples/example1.py:
--------------------------------------------------------------------------------
1 | import calfem.geometry as cfg
2 | import calfem.mesh as cfm
3 | import calfem.vis_mpl as cfv
4 |
5 | g = cfg.Geometry()
6 |
7 | # Add points
8 |
9 | g.point([0, 0]) # 0
10 | g.point([1, 0]) # 1
11 | g.point([1, 1]) # 2
12 | g.point([0, 1]) # 3
13 |
14 | # Add points for circle
15 |
16 | r = 0.20
17 |
18 | g.point([0.5, 0.5]) # 4
19 | g.point([0.5, 0.5+r]) # 5
20 | g.point([0.5, 0.5-r]) # 6
21 | g.point([0.5+r, 0.5]) # 7
22 | g.point([0.5-r, 0.5]) # 8
23 |
24 | # Add lines
25 |
26 | g.spline([0, 1]) # 0
27 | g.spline([1, 2]) # 1
28 | g.spline([2, 3]) # 2
29 | g.spline([3, 0]) # 3
30 |
31 | # TODO: Add circles HERE
32 |
33 | g.circle([5, 4, 7]) # 4
34 | g.circle([7, 4, 6]) # 5
35 | g.circle([6, 4, 8]) # 6
36 | g.circle([8, 4, 5]) # 7
37 |
38 | # Add surface and hole UPDATE
39 |
40 | g.surface([0, 1, 2, 3], [[7, 6, 5, 4]])
41 |
42 | #cfv.figure(fig_size=(10.0,10.0))
43 | #cfv.draw_geometry(g)
44 |
45 | mesh = cfm.GmshMesh(g)
46 |
47 | # Mesh properties
48 |
49 | mesh.el_type = 3
50 | mesh.dofs_per_node = 1 # Degrees of freedom per node.
51 | mesh.el_size_factor = 0.040 # Factor that changes element sizes.
52 |
53 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
54 |
55 |
56 | cfv.figure(fig_size=(10,10))
57 | cfv.draw_mesh(
58 | coords=coords,
59 | edof=edof,
60 | dofs_per_node=mesh.dofs_per_node,
61 | el_type=mesh.el_type,
62 | filled=True,
63 | title="Example 01"
64 | )
65 |
66 | cfv.show_and_wait_mpl()
67 |
--------------------------------------------------------------------------------
/examples/exd_beam2_b.py:
--------------------------------------------------------------------------------
1 | # example exd_beam2_b
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Structural Dynamics, time integration, time dependent
5 | # boundary conditions.
6 | #
7 | # Note: file exd_beam2_m.py must be in the same directory
8 | # ----------------------------------------------------------------
9 |
10 | from exd_beam2_m import *
11 |
12 | # ----- Impact, center point, vertical beam ----------------------
13 |
14 | dt = 0.002
15 | T = 1
16 |
17 | # ----- Boundary condition, initial condition --------------------
18 |
19 | G = np.array([[0, 0], [0.1, 0.02], [0.2, -0.01], [0.3, 0], [T, 0]])
20 |
21 | t, g = cfc.gfunc(G, dt)
22 |
23 | bc = np.zeros((4, 1 + len(g)))
24 | bc[0, :] = np.hstack((1, g))
25 | bc[1, 0] = 2
26 | bc[2, 0] = 3
27 | bc[3, 0] = 14
28 |
29 | a0 = np.zeros((15, 1))
30 | da0 = np.zeros((15, 1))
31 |
32 | # ----- Output parameters ----------------------------------------
33 |
34 | times = np.arange(0.1, 1.1, 0.1)
35 | dofs = np.array([1, 4, 11])
36 |
37 | # ----- Time integration parameters ------------------------------
38 |
39 | ip = np.array([dt, T, 0.25, 0.5])
40 |
41 | # ----- Time integration -----------------------------------------
42 |
43 | sol, dofhist = cfc.step2(K, [], M, [], a0, da0, bc, ip, times, dofs)
44 |
45 | # ----- Plot time history for two DOFs ---------------------------
46 |
47 | cfv.figure(1, fig_size=(7, 4))
48 | cfv.plt.plot(t, dofhist["a"][0, :], "-")
49 | cfv.plt.plot(t, dofhist["a"][1, :], "--")
50 | cfv.plt.plot(t, dofhist["a"][2, :], "-.")
51 | cfv.plt.xlim([0, 1])
52 | cfv.plt.ylim([-0.02, 0.03])
53 | cfv.plt.xlabel("time (sec)")
54 | cfv.plt.ylabel("displacement (m)")
55 | cfv.plt.title("Displacement(time) at the 1st, 4th and 11th degree of freedom")
56 | cfv.text("solid line = bottom, vertical beam, x-direction", [0.2, 0.022])
57 | cfv.text("dashed line = center, vertical beam, x-direction", [0.2, 0.017])
58 | cfv.text("dashed-dotted line = center, horizontal beam, y-direction", [0.2, 0.012])
59 | cfv.plt.grid()
60 |
61 | # ----- Plot displacement for some time increments ----------------
62 |
63 | cfv.figure(2, fig_size=(7, 5))
64 | for i in range(5):
65 | Edb = cfc.extract_ed(edof, sol["a"][:, i])
66 | ext = ex + i * 3.5
67 | cfv.eldraw2(ext, ey, [2, 3, 1])
68 | cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=20)
69 | cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
70 | eyt = ey - 4
71 | for i in range(5, 10):
72 | Edb = cfc.extract_ed(edof, sol["a"][:, i])
73 | ext = ex + (i - 5) * 3.5
74 | cfv.eldraw2(ext, eyt, [2, 3, 1])
75 | cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=20)
76 | cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
77 | cfv.title("Snapshots (sec), magnification = 20")
78 | ax = cfv.gca()
79 | ax.set_axis_off()
80 | cfv.show_and_wait()
81 |
82 | # ----- End -------------------------------------------------------
83 |
--------------------------------------------------------------------------------
/examples/exd_beam2_m.py:
--------------------------------------------------------------------------------
1 | # example exd_beam2_m
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Set up the fe-model and perform eigenvalue analysis
5 | # for a simple frame structure.
6 | # ----------------------------------------------------------------
7 |
8 | import numpy as np
9 | import calfem.core as cfc
10 | import calfem.vis_mpl as cfv
11 |
12 | # ----- Generate the model ---------------------------------------
13 | # ----- Material data --------------------------------------------
14 |
15 | E = 3e10
16 | Av = 0.1030e-2
17 | Ah = 0.0764e-2
18 | rho = 2500
19 | Iv = 0.0171e-4
20 | Ih = 0.00801e-4
21 | ep1 = [E, Av, Iv, rho * Av] # IPE100
22 | ep2 = [E, Ah, Ih, rho * Ah] # IPE80
23 |
24 | # ----- Topology -------------------------------------------------
25 |
26 | edof = np.array(
27 | [
28 | [1, 2, 3, 4, 5, 6],
29 | [4, 5, 6, 7, 8, 9],
30 | [7, 8, 9, 10, 11, 12],
31 | [10, 11, 12, 13, 14, 15],
32 | ]
33 | )
34 |
35 | # ----- List of coordinates --------------------------------------
36 |
37 | coord = np.array(
38 | [
39 | [0.0, 0.0],
40 | [0.0, 1.5],
41 | [0.0, 3.0],
42 | [1.0, 3.0],
43 | [2.0, 3.0],
44 | ]
45 | )
46 |
47 | # ----- List of degrees of freedom -------------------------------
48 |
49 | dof = np.array(
50 | [
51 | [1, 2, 3],
52 | [4, 5, 6],
53 | [7, 8, 9],
54 | [10, 11, 12],
55 | [13, 14, 15],
56 | ]
57 | )
58 |
59 | # ----- Generate element matrices, assemble in global matrices ---
60 |
61 | K = np.zeros([15, 15])
62 | M = np.zeros([15, 15])
63 |
64 | ex, ey = cfc.coordxtr(edof, coord, dof)
65 | ep = np.array([ep1, ep1, ep2, ep2])
66 |
67 | for elx, ely, eltopo, elprop in zip(ex, ey, edof, ep):
68 | Ke, Me = cfc.beam2de(elx, ely, elprop)
69 | cfc.assem(eltopo, K, Ke)
70 | cfc.assem(eltopo, M, Me)
71 |
72 | # ----- Eigenvalue analysis --------------------------------------
73 |
74 | b = np.array([1, 2, 3, 14])
75 | La, Egv = cfc.eigen(K, M, b)
76 | freq = np.sqrt(La) / (2 * np.pi)
77 |
78 | if __name__ == "__main__":
79 | # ----- Draw a plot of the element mesh --------------------------
80 |
81 | cfv.figure(1, fig_size=(5.5, 4.5))
82 | cfv.eldraw2(ex, ey, [1, 2, 1])
83 | cfv.title("2-D Frame Structure")
84 |
85 | # ----- Plot one eigenmode ---------------------------------------
86 |
87 | cfv.figure(2, fig_size=(5.5, 4.5))
88 | cfv.eldraw2(ex, ey, [2, 3, 1])
89 | Edb = cfc.extract_ed(edof, Egv[:, 0])
90 | cfv.eldisp2(ex, ey, Edb, [1, 2, 2])
91 | cfv.title("The first eigenmode")
92 | cfv.text(f"{freq[0]:.2f}", [0.5, 1.75])
93 | ax = cfv.gca()
94 | ax.grid()
95 |
96 | # ----- Plot eight eigenmodes ------------------------------------
97 |
98 | cfv.figure(3, fig_size=(7, 5))
99 | for i in range(4):
100 | Edb = cfc.extract_ed(edof, Egv[:, i])
101 | ext = ex + i * 3
102 | cfv.eldraw2(ext, ey, [2, 3, 1])
103 | cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=0.5)
104 | cfv.text(f"{freq[i]:.2f}", [3 * i + 0.5, 1.5])
105 | eyt = ey - 4
106 | for i in range(4, 8):
107 | Edb = cfc.extract_ed(edof, Egv[:, i])
108 | ext = ex + (i - 4) * 3
109 | cfv.eldraw2(ext, eyt, [2, 3, 1])
110 | cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=0.5)
111 | cfv.text(f"{freq[i]:.2f}", [3 * (i - 4) + 0.5, -2.5])
112 | cfv.title("The first eight eigenmodes [Hz]")
113 | ax = cfv.gca()
114 | ax.set_axis_off()
115 | cfv.show_and_wait()
116 |
117 | # ----- End -------------------------------------------------------
118 |
--------------------------------------------------------------------------------
/examples/exd_beam2_t.py:
--------------------------------------------------------------------------------
1 | # example exd_beam2_t
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Structural Dynamics, time integration, full system.
5 | #
6 | # Note: file exd_beam2_m.py must be in the same directory
7 | # ----------------------------------------------------------------
8 |
9 | from exd_beam2_m import *
10 |
11 | # ----- Impact, center point, vertical beam ----------------------
12 |
13 | dt = 0.002
14 | T = 1
15 |
16 | # ----- The load -------------------------------------------------
17 |
18 | G = np.array([[0, 0], [0.15, 1], [0.25, 0], [T, 0]])
19 |
20 | t, g = cfc.gfunc(G, dt)
21 | f = np.zeros((15, len(g)))
22 | f[3, :] = 1000 * g
23 |
24 | # ----- Boundary condition, initial condition --------------------
25 |
26 | bc = np.array([[1, 0], [2, 0], [3, 0], [14, 0]])
27 |
28 | a0 = np.zeros((15, 1))
29 | da0 = np.zeros((15, 1))
30 |
31 | # ----- Output parameters ----------------------------------------
32 |
33 | times = np.arange(0.1, 1.1, 0.1)
34 | dofs = np.array([4, 11])
35 |
36 | # ----- Time integration parameters ------------------------------
37 |
38 | ip = np.array([dt, T, 0.25, 0.5])
39 |
40 | # ----- Time integration -----------------------------------------
41 |
42 | sol, dofhist = cfc.step2(K, [], M, f, a0, da0, bc, ip, times, dofs)
43 |
44 | # ----- Plot time history for two DOFs ---------------------------
45 |
46 | cfv.figure(1, fig_size=(7, 4))
47 | cfv.plt.plot(t, dofhist["a"][0, :], "-")
48 | cfv.plt.plot(t, dofhist["a"][1, :], "--")
49 | cfv.plt.xlim([0, 1])
50 | cfv.plt.ylim([-0.01, 0.02])
51 | cfv.plt.xlabel("time (sec)")
52 | cfv.plt.ylabel("displacement (m)")
53 | cfv.plt.title("Displacement(time) at the 4th and 11th degree of freedom")
54 | cfv.text("solid line = impact point, x-direction", [0.3, 0.017])
55 | cfv.text("dashed line = center, horizontal beam, y-direction", [0.3, 0.012])
56 | cfv.plt.grid()
57 |
58 | # ----- Plot displacement for some time increments ----------------
59 |
60 | cfv.figure(2, fig_size=(7, 5))
61 | for i in range(5):
62 | Edb = cfc.extract_ed(edof, sol["a"][:, i])
63 | ext = ex + i * 3.5
64 | cfv.eldraw2(ext, ey, [2, 3, 1])
65 | cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=25)
66 | cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
67 | eyt = ey - 4
68 | for i in range(5, 10):
69 | Edb = cfc.extract_ed(edof, sol["a"][:, i])
70 | ext = ex + (i - 5) * 3.5
71 | cfv.eldraw2(ext, eyt, [2, 3, 1])
72 | cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=25)
73 | cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
74 | cfv.title("Snapshots (sec), magnification = 25")
75 | ax = cfv.gca()
76 | ax.set_axis_off()
77 | cfv.show_and_wait()
78 |
79 | # ----- End -------------------------------------------------------
80 |
--------------------------------------------------------------------------------
/examples/exd_beam2_tr.py:
--------------------------------------------------------------------------------
1 | # example exd_beam2_tr
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Structural Dynamics, time integration, reduced system.
5 | #
6 | # Note: file exd_beam2_m.py must be in the same directory
7 | # ----------------------------------------------------------------
8 |
9 | from exd_beam2_m import *
10 |
11 | # ----- Impact, center point, vertical beam ----------------------
12 |
13 | dt = 0.002
14 | T = 1
15 | nev = 2
16 |
17 | # ----- The load -------------------------------------------------
18 |
19 | G = np.array([[0, 0], [0.15, 1], [0.25, 0], [T, 0]])
20 |
21 | t, g = cfc.gfunc(G, dt)
22 | f = np.zeros((15, len(g)))
23 | f[3, :] = 1000 * g
24 | fr = np.hstack((np.arange(1, nev + 1).reshape(-1, 1), Egv[:, :nev].T @ f))
25 |
26 | # ----- Reduced system matrices ----------------------------------
27 |
28 | kr = np.diag(np.diag(Egv[:, :nev].T @ K @ Egv[:, :nev]))
29 | mr = np.diag(np.diag(Egv[:, :nev].T @ M @ Egv[:, :nev]))
30 |
31 | # ----- Initial condition ----------------------------------------
32 |
33 | ar0 = np.zeros((nev, 1))
34 | dar0 = np.zeros((nev, 1))
35 |
36 | # ----- Output parameters ----------------------------------------
37 |
38 | times = np.arange(0.1, 1.1, 0.1)
39 | dofsr = np.arange(1, nev + 1)
40 | dofs = np.array([4, 11])
41 |
42 | # ----- Time integration parameters ------------------------------
43 |
44 | ip = np.array([dt, T, 0.25, 0.5])
45 |
46 | # ----- Time integration -----------------------------------------
47 | sol, dofhist = cfc.step2(kr, [], mr, fr, ar0, dar0, [], ip, times, dofsr)
48 |
49 | # ----- Mapping back to original coordinate system ---------------
50 |
51 | aR = Egv[:, :nev] @ sol["a"]
52 | aRhist = Egv[dofs - 1, :nev] @ dofhist["a"]
53 |
54 | # ----- Plot time history for two DOFs ---------------------------
55 |
56 | cfv.figure(1, fig_size=(7, 4))
57 | cfv.plt.plot(t, aRhist[0, :], "-")
58 | cfv.plt.plot(t, aRhist[1, :], "--")
59 | cfv.plt.xlim([0, 1])
60 | cfv.plt.ylim([-0.01, 0.02])
61 | cfv.plt.xlabel("time (sec)")
62 | cfv.plt.ylabel("displacement (m)")
63 | cfv.plt.title("Displacement(time) at the 4th and 11th degree of freedom")
64 | cfv.text("solid line = impact point, x-direction", [0.3, 0.017])
65 | cfv.text("dashed line = center, horizontal beam, y-direction", [0.3, 0.012])
66 | cfv.text("TWO EIGENVECTORS ARE USED", [0.3, -0.007])
67 | cfv.plt.grid()
68 |
69 | # ----- Plot displacement for some time increments ----------------
70 |
71 | cfv.figure(2, fig_size=(7, 5))
72 |
73 | for i in range(5):
74 | Edb = cfc.extract_ed(edof, aR[:, i])
75 | ext = ex + i * 3.5
76 | cfv.eldraw2(ext, ey, [2, 3, 1])
77 | cfv.eldisp2(ext, ey, Edb, [1, 2, 2], sfac=25)
78 | cfv.text(f"{times[i]:.1f}", [3.5 * i + 0.5, 1.5])
79 |
80 | eyt = ey - 4
81 |
82 | for i in range(5, 10):
83 | Edb = cfc.extract_ed(edof, aR[:, i])
84 | ext = ex + (i - 5) * 3.5
85 | cfv.eldraw2(ext, eyt, [2, 3, 1])
86 | cfv.eldisp2(ext, eyt, Edb, [1, 2, 2], sfac=25)
87 | cfv.text(f"{times[i]:.1f}", [3.5 * (i - 5) + 0.5, -2.5])
88 |
89 | cfv.title("Snapshots (sec), magnification = 25")
90 | ax = cfv.gca()
91 | ax.set_axis_off()
92 | cfv.show_and_wait()
93 |
94 | # ----- End -------------------------------------------------------
95 |
--------------------------------------------------------------------------------
/examples/exe_stress_2d_editor.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | CALFEM Editor Example
5 |
6 | Written by Karl Eriksson
7 | """
8 |
9 | import calfem.editor as cfe
10 | import calfem.geometry as cfg
11 | import calfem.mesh as cfm
12 | import calfem.vis_mpl as cfv
13 | import calfem.utils as cfu
14 | import calfem.core as cfc
15 | import numpy as np
16 |
17 | # --- Creating a square geometry with two markers
18 |
19 | g = cfg.Geometry()
20 |
21 | g.point([0.0, 0.0]) # point 0
22 | g.point([100.0, 0.0]) # point 1
23 | g.point([100, 100]) # point 2
24 | g.point([0, 100]) # point 3
25 |
26 | g.spline([0, 1]) # line 0
27 | g.spline([1, 2]) # line 1
28 | g.spline([2, 3]) # line 2
29 | g.spline([3, 0]) # line 3
30 |
31 | g.surface([0, 1, 2, 3]) # Connect lines to form surface
32 | g.setCurveMarker(0, 10)
33 | g.setCurveMarker(2, 20)
34 |
35 | # --- Open the geometry to allow changes in the CALFEM Geometry Editor
36 |
37 | new_geometry, marker_dict = cfe.edit_geometry(g)
38 | print(marker_dict)
39 |
40 | t = 0.2
41 | v = 0.35
42 | E = 2.1e9
43 | ptype = 1
44 | ep = [ptype, t]
45 | D = cfc.hooke(ptype, E, v)
46 |
47 | # --- Every border or point marked with 10 will recieve boundary
48 | # --- condition value of 0
49 |
50 | bcs_new = [[marker_dict[10], 0]]
51 |
52 | # --- Every border or point marked with 20 will recieve load
53 | # --- value of 10e5
54 |
55 | loads_new = [[marker_dict[20], 10e5]]
56 |
57 | # --- Every border or point marked with A will recieve boundary
58 | # --- condition value of 0
59 |
60 | bcs_old = [[10, 0]]
61 |
62 | # --- Every border or point marked with B will recieve load
63 | # --- value of 10e5
64 |
65 | loads_old = [[20, 10e5]]
66 |
67 | el_size_factor = 5
68 | el_type = 3
69 | dofs_per_node = 2
70 |
71 |
72 | def calc(geometry, bcs, loads, text):
73 | mesh = cfm.GmshMeshGenerator(geometry)
74 | mesh.el_size_factor = el_size_factor # Factor that changes element sizes.
75 | mesh.el_type = el_type
76 | mesh.dofs_per_node = dofs_per_node
77 |
78 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
79 |
80 | # --- Calculate element coordinates
81 |
82 | ex, ey = cfc.coordxtr(edof, coords, dofs)
83 |
84 | # --- Assemble system matrix
85 |
86 | nDofs = edof.max()
87 |
88 | K = np.zeros([nDofs, nDofs])
89 |
90 | for eltopo, elx, ely in zip(edof, ex, ey):
91 | Ke = cfc.planqe(elx, ely, ep, D)
92 | cfc.assem(eltopo, K, Ke)
93 |
94 | # --- Solve equation system
95 |
96 | f = np.zeros([nDofs, 1])
97 | bcPrescr = np.array([], int)
98 | bcVal = np.array([], float)
99 |
100 | for bc in bcs:
101 | bcPrescr, bcVal = cfu.applybc(bdofs, bcPrescr, bcVal, bc[0], bc[1])
102 |
103 | for load in loads:
104 | cfu.applyforcetotal(bdofs, f, load[0], load[1])
105 |
106 | a, r = cfc.solveq(K, f, bcPrescr, bcVal)
107 |
108 | # --- Calculate element forces
109 |
110 | ed = cfc.extractEldisp(edof, a)
111 |
112 | vonMises = []
113 |
114 | # --- For each element:
115 |
116 | for i in range(edof.shape[0]):
117 | # --- Determine element stresses and strains in the element.
118 |
119 | es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
120 |
121 | # --- Calc and append effective stress to list.
122 | vonMises.append(
123 | np.sqrt(np.power(es[0], 2) - es[0] * es[1] + np.power(es[1], 2) + 3 * es[2])
124 | )
125 |
126 | title = "Effective stress" + text
127 | cfv.draw_element_values(
128 | vonMises,
129 | coords,
130 | edof,
131 | mesh.dofs_per_node,
132 | mesh.el_type,
133 | None,
134 | draw_elements=False,
135 | draw_undisplaced_mesh=False,
136 | title=title,
137 | )
138 |
139 |
140 | # --- Display results
141 |
142 | cfv.clf()
143 | calc(g, bcs_old, loads_old, " original")
144 | cfv.figure()
145 | calc(new_geometry, bcs_new, loads_new, " modified")
146 | cfv.show_and_wait()
147 |
--------------------------------------------------------------------------------
/examples/exm_circle_bsplines.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """
4 | Example 02
5 | Creating geometry from B-Splines and circle arcs.
6 | Also shows how to set ID numbers for geometry entities and how to specify element density.
7 | """
8 |
9 | import matplotlib.pyplot as plt
10 | import matplotlib.collections
11 | import numpy as np
12 |
13 | import calfem.geometry as cfg
14 | import calfem.mesh as cfm
15 | import calfem.vis_mpl as cfv
16 |
17 | # ---- Define geometry ------------------------------------------------------
18 |
19 | g = cfg.Geometry()
20 |
21 | # Add points:
22 | # In this example we set the IDs manually.
23 |
24 | g.point([-2, 0], ID=0)
25 | # el_size determines the size of the elements near this point.
26 | g.point([0, 1], ID=1, el_size=5)
27 | # el_size is 1 by default. Larger number means less dense mesh.
28 | g.point([1, 0], 2, el_size=5)
29 | g.point([0, -2], 3) # Size means the length of the sides of the elements.
30 | g.point([0, 0], 4, el_size=5)
31 | g.point([0.5, 0.2], 5)
32 | g.point([-0.5, 0.5], 6)
33 | g.point([-0.7, -0.5], 7)
34 |
35 | # Add curves:
36 |
37 | # The 3 points that define the circle arc are [start, center, end].
38 | # The arc must be smaller than Pi.
39 |
40 | g.circle([1, 4, 2], 2)
41 |
42 | # BSplines are similar to Splines, but do not necessarily pass through the
43 | # control points.
44 |
45 | g.bspline([5, 6, 7, 5], 5)
46 | g.bspline([1, 0, 3, 2], 4)
47 |
48 | # Add surface:
49 |
50 | g.surface([4, 2], [[5]])
51 |
52 | # Markers do not have to be set when the curve is created. It can be done afterwards.
53 | # Set marker=80 for curves 2 and 4:
54 |
55 | for curveID in [2, 4]:
56 | g.curveMarker(curveID, 80)
57 |
58 | # ---- Generate mesh --------------------------------------------------------
59 |
60 | mesh = cfm.GmshMesh(g)
61 |
62 | # Element type 2 is triangle. (3 is quad. See user manual for more element types)
63 |
64 | mesh.el_type = 3
65 |
66 | # Degrees of freedom per node.
67 |
68 | mesh.dofs_per_node = 2
69 | mesh.el_size_factor = 0.05
70 | # mesh.gmsh_exec_path = "D:\\vsmn20-software\\gmsh\gmsh.exe"
71 |
72 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
73 |
74 | # ---- Visualise mesh -------------------------------------------------------
75 |
76 | # Hold left mouse button to pan.
77 | # Hold right mouse button to zoom.
78 |
79 | # Draw the geometry.
80 |
81 | cfv.figure()
82 | cfv.draw_geometry(g, label_curves=True, title="Example 2 - Geometry")
83 |
84 | # Draws the mesh.
85 |
86 | cfv.figure()
87 | cfv.draw_mesh(
88 | coords=coords,
89 | edof=edof,
90 | dofs_per_node=mesh.dofs_per_node,
91 | el_type=mesh.el_type,
92 | filled=True,
93 | title="Example 2 - Mesh",
94 | )
95 |
96 | # Enter main loop
97 |
98 | cfv.show_and_wait()
99 |
--------------------------------------------------------------------------------
/examples/exm_flow_model.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exm0_mpl.py
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Setup a finite element flow model using the mesh functions
7 | # in CALFEM.
8 | # ----------------------------------------------------------------
9 | #
10 | # REFERENCES
11 | # J Lindemann 2021-12-29
12 | # ----------------------------------------------------------------
13 |
14 | # ----- Import needed modules ------------------------------------
15 |
16 | import numpy as np
17 | import calfem.core as cfc
18 | import calfem.geometry as cfg
19 | import calfem.mesh as cfm
20 | import calfem.vis_mpl as cfv
21 | import calfem.utils as cfu
22 |
23 | # ----- Problem parameters ---------------------------------------
24 |
25 | w = 100.0
26 | h = 10.0
27 | t = 1.0
28 | d = h / 2
29 |
30 | D = np.identity(2, "float")
31 | ep = [1.0, 1]
32 |
33 | # ----- Create geometry object -----------------------------------
34 |
35 | g = cfg.Geometry()
36 |
37 | g.point([0, 0]) # point 1
38 | g.point([w, 0]) # point 2
39 | g.point([w, h]) # point 3
40 | g.point([w - w / 2 + t / 2, h]) # point 4
41 | g.point([w - w / 2 + t / 2, h - d]) # point 5
42 | g.point([w - w / 2 - t / 2, h - d]) # point 6
43 | g.point([w - w / 2 - t / 2, h]) # point 7
44 | g.point([0, h]) # point 8
45 |
46 | # ----- Create lines between points ------------------------------
47 |
48 | left_side = 80
49 | right_side = 90
50 |
51 | g.spline([0, 1])
52 | g.spline([1, 2])
53 | g.spline([2, 3], marker=left_side) # marker just to name
54 | g.spline([3, 4])
55 | g.spline([4, 5])
56 | g.spline([5, 6])
57 | g.spline([6, 7], marker=right_side)
58 | g.spline([7, 0])
59 |
60 | # ----- Make surface area ----------------------------------------
61 |
62 | g.surface([0, 1, 2, 3, 4, 5, 6, 7])
63 |
64 | # ----- Mesh generation ------------------------------------------
65 |
66 | el_type = 3 # quadrature element
67 | dofs_per_node = 1 # 1 dof
68 |
69 | # ----- Set mesh paramters ---------------------------------------
70 |
71 | mesh = cfm.GmshMesh(g)
72 | mesh.el_size_factor = 1.0
73 | mesh.el_type = el_type
74 | mesh.dofs_per_node = dofs_per_node
75 |
76 | # ----- Create mesh ----------------------------------------------
77 |
78 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
79 |
80 | # ----- Assemble elements ----------------------------------------
81 |
82 | nDofs = np.size(dofs)
83 | ex, ey = cfc.coordxtr(edof, coords, dofs)
84 | K = np.zeros([nDofs, nDofs])
85 |
86 | for eltopo, elx, ely in zip(edof, ex, ey):
87 | Ke = cfc.flw2i4e(elx, ely, ep, D)
88 | cfc.assem(eltopo, K, Ke)
89 |
90 | # ----- Force vector ---------------------------------------------
91 |
92 | f = np.zeros([nDofs, 1])
93 |
94 | # ----- Boundary conditions --------------------------------------
95 |
96 | bc = np.array([], int)
97 | bcVal = np.array([], int)
98 |
99 | bc, bcVal = cfu.applybc(bdofs, bc, bcVal, left_side, 0.0)
100 | bc, bcVal = cfu.applybc(bdofs, bc, bcVal, right_side, 10.0)
101 |
102 | # ----- Solve equation system ------------------------------------
103 |
104 | a, r = cfc.solveq(K, f, bc, bcVal)
105 | ed = cfc.extractEldisp(edof, a)
106 |
107 | # ----- Calculating element forces -------------------------------
108 |
109 | maxFlow = [] # empty list to store flow
110 |
111 | for i in range(edof.shape[0]):
112 | es, et, eci = cfc.flw2i4s(ex[i, :], ey[i, :], ep, D, ed[i, :])
113 | maxFlow.append(np.sqrt(pow(es[0, 0], 2) + pow(es[0, 1], 2)))
114 |
115 | # ----- Visualize results ----------------------------------------
116 |
117 | cfv.figure()
118 | cfv.draw_geometry(g, title="Geometry")
119 |
120 | cfv.figure()
121 | cfv.draw_element_values(
122 | maxFlow, coords, edof, dofs_per_node, el_type, None, title="Max flows"
123 | )
124 |
125 | cfv.figure()
126 | cfv.draw_nodal_values(a, coords, edof, dofs_per_node=dofs_per_node, el_type=el_type)
127 |
128 | cfv.showAndWait()
129 |
--------------------------------------------------------------------------------
/examples/exm_geometry.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 01
4 |
5 | Shows how to create simple geometry from splines and ellipse arcs, and how to mesh a quad mesh in GmshMesher.
6 | Also demonstrates drawGeometry(), drawMesh, and drawing texts and labels in a figure.
7 | """
8 |
9 | import calfem.geometry as cfg
10 | import calfem.mesh as cfm
11 | import calfem.vis_mpl as cfv
12 |
13 | # ---- Define geometry ------------------------------------------------------
14 |
15 | g = cfg.Geometry() # Create a GeoData object that holds the geometry.
16 |
17 | # Add points:
18 | # The first parameter is the coordinates. These can be in 2D or 3D.
19 | # The other parameters are not defined in this example. These parameters are
20 | # ID, marker, and elSize.
21 | # Since we do not specify an ID the points are automatically assigned IDs,
22 | # starting from 0.
23 |
24 | g.point([0, 0])
25 | g.point([2, 0])
26 | g.point([2, 1])
27 | g.point([0, 1])
28 | g.point([0.5, 0.3])
29 | g.point([0.3, 0.7])
30 | g.point([0.7, 0.7])
31 | g.point([0.8, 0.5])
32 | g.point([1.7, 0.5])
33 | g.point([1.5, 0.5])
34 | g.point([1.7, 0.7])
35 |
36 | # Add curves:
37 | # There are four types of curves. In this example we create an ellipse arc
38 | # and some splines. The first parameter is a list of point IDs that define
39 | # the curve. Curves can have have IDs and markers. In this example the IDs
40 | # are undefined so the curves are automatically assigned IDs. The markers can
41 | # be used for identifying regions/boundaries in the model.
42 |
43 |
44 | # 0 - An ellipse arc. Read the function
45 | # doc for more information. The four
46 | # points are
47 | # [start, center, majorAxis, end]
48 |
49 | g.ellipse([7, 8, 9, 10], marker=50)
50 |
51 | g.spline([0, 1], marker=80) # 1 - A spline. Splines pass through the
52 | # points in the first parameter.
53 | g.spline([2, 1]) # 2
54 | g.spline([3, 2]) # 3
55 | g.spline([0, 3]) # 4
56 | g.spline([7, 9], marker=50) # 5
57 | g.spline([10, 9]) # 6
58 | g.spline([4, 5, 6, 4]) # 7 - This is a closed spline.
59 | # The start and end points are the same
60 |
61 | # Add a surface:
62 | # Surfaces are defined by its curve boundaries.
63 | # The first parameter is a list of curve IDs that specify the outer boundary
64 | # of the surface. The second parameter is a list of lists of curve IDs that
65 | # specify holes in the surface. In this example there are two holes. The
66 | # boundaries and holes must be closed paths. We can see that [7] is closed
67 | # because curve 7 is a closed spline. addSurface creates a flat surface, so
68 | # all curves must lie on the same plane.
69 |
70 | g.surface([4, 3, 2, 1], [[7], [5, 6, 0]])
71 |
72 | # ---- Generate mesh --------------------------------------------------------
73 |
74 | mesh = cfm.GmshMesh(g)
75 |
76 | # Element type 3 is quad.
77 | # (2 is triangle. See user manual for more element types)
78 |
79 | mesh.el_type = 3
80 | mesh.dofs_per_node = 1 # Degrees of freedom per node.
81 | mesh.el_size_factor = 0.05 # Factor that changes element sizes.
82 | # mesh.mesh_dir = "./mesh_files"
83 | # mesh.gmsh_exec_path = "D:\\vsmn20-software\\gmsh\gmsh.exe"
84 |
85 | # Mesh the geometry:
86 | #
87 | # The first four return values are the same as those that trimesh2d() returns.
88 | # coords is as list of node coordinates. edof is the element topology
89 | # (element degrees of freedom). dofs is a lists of all degrees of freedom
90 | # bdofs is a dictionary of boundary dofs (dofs of geometric entities with
91 | # markers). elementmarkers is a list of markers, and is used for finding the
92 | # marker of a given element (index).
93 |
94 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
95 |
96 | # ---- Visualise mesh -------------------------------------------------------
97 |
98 | # Hold left mouse button to pan.
99 | # Hold right mouse button to zoom.
100 |
101 | # Draw the geometry. Note that surfaces and volumes are not drawn at all by
102 | # this function.
103 |
104 | cfv.figure()
105 | cfv.draw_geometry(g)
106 |
107 | # Draw the mesh.
108 |
109 | cfv.figure()
110 | cfv.draw_mesh(
111 | coords=coords,
112 | edof=edof,
113 | dofs_per_node=mesh.dofs_per_node,
114 | el_type=mesh.el_type,
115 | filled=True,
116 | title="Example 01",
117 | )
118 |
119 | # Adds a text in world space
120 |
121 | cfv.text("This is a Text", pos=(1, -0.3), rotation=45)
122 |
123 | # Adds a label in the screen space
124 |
125 | our_label = cfv.label("This is a Label", pos=(1, 0.3), rotation=-45)
126 |
127 | # We can change the attributes of labels and texts, such as color, text, and position.
128 |
129 | our_label.set_text("Label, changed.")
130 | our_label.set_color("r") # Make it red. (1,0,0) would also have worked.
131 | our_label.set_position((1, 0.3))
132 |
133 | # Enter main loop:
134 |
135 | cfv.show_and_wait()
136 |
--------------------------------------------------------------------------------
/examples/exm_qt_vis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Example illustrating how to integrate CALFEM in a PyQt application
4 | """
5 |
6 | import sys
7 | import time
8 |
9 | from calfem.qt5 import *
10 |
11 | import calfem.geometry as cfg
12 | import calfem.mesh as cfm
13 | import calfem.vis as cfv
14 |
15 | class MainWindow(QMainWindow):
16 | def __init__(self):
17 | """Constructor"""
18 | super(MainWindow, self).__init__()
19 |
20 | # Load user interface from UI-file
21 |
22 | loadUi('exm_qt_vis.ui', self)
23 |
24 | Figure = cfv.figureClass()
25 |
26 | self.fig1 = Figure(self)
27 | self.fig2 = Figure(self)
28 |
29 | self.gridLayout.addWidget(self.fig1._widget, 0, 0)
30 | self.gridLayout.addWidget(self.fig2._widget, 0, 1)
31 |
32 | print(self.fig1._widget)
33 |
34 |
35 | @Slot()
36 | def on_executeButton_clicked(self):
37 | self.solveProblem()
38 | self.drawGeometry()
39 | self.drawMesh()
40 |
41 |
42 | def solveProblem(self):
43 |
44 | g = cfg.Geometry() #Create a GeoData object that holds the geometry.
45 |
46 | g.point([0, 0])
47 | g.point([2, 0])
48 | g.point([2, 1])
49 | g.point([0, 1])
50 | g.point([0.5, 0.3])
51 | g.point([0.3, 0.7])
52 | g.point([0.7, 0.7])
53 | g.point([0.8, 0.5])
54 | g.point([1.7, 0.5])
55 | g.point([1.5, 0.5])
56 | g.point([1.7, 0.7])
57 |
58 | g.ellipse([7,8,9,10], marker=50) # 0 - An ellipse arc. Read the function
59 | g.spline([0, 1], marker=80) # 1 - A spline. Splines pass through the
60 | g.spline([2, 1]) # 2
61 | g.spline([3, 2]) # 3
62 | g.spline([0, 3]) # 4
63 | g.spline([7, 9], marker=50) # 5
64 | g.spline([10, 9]) # 6
65 | g.spline([4, 5, 6, 4]) # 7 - This is a closed spline.
66 |
67 | g.surface([4,3,2,1], [[7], [5,6,0]])
68 |
69 | meshGen = cfm.GmshMeshGenerator(g)
70 |
71 | meshGen.elType = 3 # Degrees of freedom per node.
72 | meshGen.dofsPerNode = 1 # Factor that changes element sizes.
73 | meshGen.elSizeFactor = 0.05
74 |
75 | self.coords, self.edof, self.dofs, self.bdofs, self.elementmarkers = meshGen.create()
76 | self.meshGen = meshGen
77 | self.g = g
78 |
79 | def drawGeometry(self):
80 | cfv.figure(self.fig1.nr)
81 | cfv.clf()
82 | cfv.drawGeometry(self.g)
83 |
84 | def drawMesh(self):
85 | cfv.figure(self.fig2.nr)
86 | cfv.clf()
87 | cfv.draw_mesh(
88 | coords=self.coords,
89 | edof=self.edof,
90 | dofs_per_node=self.meshGen.dofsPerNode,
91 | el_type=self.meshGen.elType,
92 | filled=True,
93 | title="Example 01"
94 | )
95 |
96 | cfv.addText("This is a Text", pos=(1, -0.3), angle=45) #Adds a text in world space
97 |
98 | ourLabel = cfv.label("This is a Label", pos=(100,200), angle=-45) #Adds a label in the screen space
99 | ourLabel.text = "Label, changed." #We can change the attributes of labels and texts, such as color, text, and position.
100 | ourLabel.textColor = 'r' #Make it red. (1,0,0) would also have worked.
101 | ourLabel.position = (20,30)
102 |
103 |
104 | if __name__ == "__main__":
105 |
106 | app = QApplication(sys.argv)
107 | widget = MainWindow()
108 | widget.show()
109 | sys.exit(app.exec_())
110 |
--------------------------------------------------------------------------------
/examples/exm_qt_vis.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 806
10 | 559
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 0
23 | 0
24 |
25 |
26 |
27 |
28 | 16777215
29 | 50
30 |
31 |
32 |
33 | QFrame::StyledPanel
34 |
35 |
36 | QFrame::Raised
37 |
38 |
39 |
-
40 |
41 |
42 | Execute
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Qt::Horizontal
50 |
51 |
52 |
53 | 40
54 | 20
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | -
63 |
64 |
65 |
66 |
67 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/examples/exm_stress_2d_qt.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 806
10 | 559
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 | 0
23 | 0
24 |
25 |
26 |
27 |
28 | 16777215
29 | 50
30 |
31 |
32 |
33 | QFrame::StyledPanel
34 |
35 |
36 | QFrame::Raised
37 |
38 |
39 |
-
40 |
41 |
42 | Execute
43 |
44 |
45 |
46 | -
47 |
48 |
49 | Qt::Horizontal
50 |
51 |
52 |
53 | 40
54 | 20
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 | -
63 |
64 |
65 |
66 |
67 |
77 |
78 |
79 |
80 |
81 |
82 |
--------------------------------------------------------------------------------
/examples/exm_structured_mesh.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 04.
4 |
5 | Structured 3D meshing. Adding texts and labels to figures. Altering axis properties.
6 | """
7 |
8 | import calfem.geometry as cfg
9 | import calfem.mesh as cfm
10 | import calfem.vis_mpl as cfv
11 |
12 | # ---- Define geometry ------------------------------------------------------
13 |
14 | g = cfg.geometry()
15 |
16 | # Add Points
17 |
18 | g.point([0, 0, 0], ID=0)
19 | g.point([0.5, -0.3, -0.3], 1)
20 | g.point([1, 0, 0], 2)
21 | g.point([1, 1, 0], 3)
22 | g.point([0, 1, 0], 4, marker=11) # Set some markers no reason.
23 | g.point([0, 0, 1], 5, marker=11) # (markers can be given to points as well
24 | # as curves and surfaces)
25 | g.point([1, 0, 1], 6, marker=11)
26 | g.point([1, 1, 1], 7)
27 | g.point([0, 1, 1], 8)
28 |
29 | # Add splines
30 |
31 | g.spline([0, 1, 2], 0, marker=33, el_on_curve=5)
32 | g.spline([2, 3], 1, marker=23, el_on_curve=5)
33 | g.spline([3, 4], 2, marker=23, el_on_curve=5)
34 | g.spline([4, 0], 3, el_on_curve=5)
35 | g.spline([0, 5], 4, el_on_curve=5)
36 | g.spline([2, 6], 5, el_on_curve=5)
37 | g.spline([3, 7], 6, el_on_curve=5)
38 | g.spline([4, 8], 7, el_on_curve=5)
39 | g.spline([5, 6], 8, el_on_curve=5)
40 | g.spline([6, 7], 9, el_on_curve=5)
41 | g.spline([7, 8], 10, el_on_curve=5)
42 | g.spline([8, 5], 11, el_on_curve=5)
43 |
44 | # Add surfaces
45 |
46 | g.structuredSurface([0, 1, 2, 3], 0, marker=45)
47 | g.structuredSurface([8, 9, 10, 11], 1)
48 | g.structuredSurface([0, 4, 8, 5], 2, marker=55)
49 | g.structuredSurface([1, 5, 9, 6], 3, marker=55)
50 | g.structuredSurface([2, 6, 10, 7], 4)
51 | g.structuredSurface([3, 4, 11, 7], 5)
52 |
53 | # Add Volume:
54 | # addStructuredVolume() takes three args. The first is a list of surface IDs
55 | # (structured surfaces). The surfaces should make a hexahedron
56 | # (i.e. 6 surfaces). Other kinds of structured volumes than hexahedra will
57 | # not work for hexahedral elements, which is the only type of 3D element that
58 | # CALFEM handles. The two optional parameters are the volume ID and
59 | # volume marker.
60 |
61 | g.structuredVolume([0, 1, 2, 3, 4, 5], 0, marker=90)
62 |
63 | # ---- Create mesh ----------------------------------------------------------
64 |
65 | # Element type 5 is hexahedron. (See user manual for more element types)
66 | el_type = 5 # error here, element type not implemented
67 |
68 | # Degrees of freedom per node.
69 | dofs_per_node = 1
70 |
71 | # Create mesh
72 | coords, edof, dofs, bdofs, _ = cfm.mesh(g, el_type, dofs_per_node)
73 |
74 | # coords, edof, dofs, bdofs, _ = cfm.mesh(
75 | # g, el_type, dofs_per_node,
76 | # gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
77 |
78 | # ---- Visualise mesh -------------------------------------------------------
79 |
80 | # Hold Left Mouse button to rotate.
81 | # Hold right mouse button to zoom.
82 | # Hold SHIFT and left mouse button to pan.
83 | # Hold SHIFT and right mouse button to change the field of view.
84 | # Hold Ctrl and left mouse button to roll the camera.
85 |
86 | # Draw geometry
87 |
88 | cfv.draw_geometry(g, draw_points=False)
89 |
90 | # Draw mesh
91 |
92 | cfv.figure()
93 | cfv.draw_mesh(
94 | coords=coords, edof=edof, dofs_per_node=dofs_per_node, el_type=el_type, filled=True
95 | )
96 |
97 | # Add a text in world space
98 |
99 | # cfv.add_text("This is a Text", pos=(1, 0.5, 0.5), angle=45)
100 |
101 | # Add a label in the screen space
102 |
103 | # our_label = cfv.add_label("This is a Label", pos=(20,30), angle=-45)
104 |
105 | # We can change the attributes of labels and texts, such as color and position.
106 |
107 | # our_label.text = "Label, changed."
108 |
109 | # Make it red. (1,0,0) would also have worked.
110 |
111 | # our_label.textColor = 'r'
112 |
113 | # Matlab style axes (three axes in the background instead of a cube)
114 |
115 | # cfv.gca().axis.showBox = 0
116 |
117 | # Change the limits of the axes.
118 |
119 | # cfv.gca().SetLimits(rangeX=(0,2), rangeY=(-1,1.5), rangeZ=(-0.5,2), margin=0.02)
120 |
121 | # Enter main loop
122 |
123 | cfv.show_and_wait()
124 |
--------------------------------------------------------------------------------
/examples/exm_structured_mesh_3d.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 04.
4 |
5 | Structured 3D meshing. Adding texts and labels to figures. Altering axis properties.
6 | """
7 |
8 | import calfem.geometry as cfg
9 | import calfem.mesh as cfm
10 | import calfem.vis_vtk as cfv
11 |
12 | # ---- Define geometry ------------------------------------------------------
13 |
14 | g = cfg.geometry()
15 |
16 | # Add Points
17 |
18 | g.point([0, 0, 0], ID=0)
19 | g.point([0.5, -0.3, -0.3], 1)
20 | g.point([1, 0, 0], 2)
21 | g.point([1, 1, 0], 3)
22 | g.point([0, 1, 0], 4, marker=11) # Set some markers no reason.
23 | g.point([0, 0, 1], 5, marker=11) # (markers can be given to points as well
24 | # as curves and surfaces)
25 | g.point([1, 0, 1], 6, marker=11)
26 | g.point([1, 1, 1], 7)
27 | g.point([0, 1, 1], 8)
28 |
29 | # Add splines
30 |
31 | g.spline([0, 1, 2], 0, marker=33, el_on_curve=5)
32 | g.spline([2, 3], 1, marker=23, el_on_curve=5)
33 | g.spline([3, 4], 2, marker=23, el_on_curve=5)
34 | g.spline([4, 0], 3, el_on_curve=5)
35 | g.spline([0, 5], 4, el_on_curve=5)
36 | g.spline([2, 6], 5, el_on_curve=5)
37 | g.spline([3, 7], 6, el_on_curve=5)
38 | g.spline([4, 8], 7, el_on_curve=5)
39 | g.spline([5, 6], 8, el_on_curve=5)
40 | g.spline([6, 7], 9, el_on_curve=5)
41 | g.spline([7, 8], 10, el_on_curve=5)
42 | g.spline([8, 5], 11, el_on_curve=5)
43 |
44 | # Add surfaces
45 |
46 | g.structuredSurface([0, 1, 2, 3], 0, marker=45)
47 | g.structuredSurface([8, 9, 10, 11], 1)
48 | g.structuredSurface([0, 4, 8, 5], 2, marker=55)
49 | g.structuredSurface([1, 5, 9, 6], 3, marker=55)
50 | g.structuredSurface([2, 6, 10, 7], 4)
51 | g.structuredSurface([3, 4, 11, 7], 5)
52 |
53 | # Add Volume:
54 | # addStructuredVolume() takes three args. The first is a list of surface IDs
55 | # (structured surfaces). The surfaces should make a hexahedron
56 | # (i.e. 6 surfaces). Other kinds of structured volumes than hexahedra will
57 | # not work for hexahedral elements, which is the only type of 3D element that
58 | # CALFEM handles. The two optional parameters are the volume ID and
59 | # volume marker.
60 |
61 | g.structuredVolume([0, 1, 2, 3, 4, 5], 0, marker=90)
62 |
63 | # ---- Create mesh ----------------------------------------------------------
64 |
65 | # Element type 5 is hexahedron. (See user manual for more element types)
66 |
67 | el_type = 5
68 |
69 | # Degrees of freedom per node.
70 |
71 | dofs_per_node = 1
72 |
73 | # Create mesh
74 |
75 | coords, edof, dofs, bdofs, _ = cfm.mesh(g, el_type, 1, dofs_per_node)
76 |
77 | # coords, edof, dofs, bdofs, _ = cfm.mesh(
78 | # g, el_type, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
79 |
80 | # ---- Visualise mesh -------------------------------------------------------
81 |
82 | cfv.draw_mesh(coords, edof, el_type)
83 |
--------------------------------------------------------------------------------
/examples/exm_structured_mesh_vtk.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 03
4 |
5 | Shows structured meshing in 2D.
6 | """
7 |
8 | import calfem.geometry as cfg
9 | import calfem.mesh as cfm
10 | import calfem.vis_mpl as cfv
11 |
12 | # ---- Define geometry ------------------------------------------------------
13 |
14 | g = cfg.Geometry()
15 |
16 | # Add Points:
17 |
18 | g.point([0, 0])
19 | g.point([1.2, 0])
20 | g.point([1, 1.3])
21 | g.point([0, 1])
22 | g.point([2, 0.5])
23 |
24 | # Add Splines:
25 | # The first four curves are structured curves, i.e the number of nodes along
26 | # the curves is pre-determined. Parameter el_on_curve states how many elements
27 | # are placed along the curve. Parameters el_distrib_type and el_distrib_val are
28 | # optional parameters that specify how elements are distributed.
29 | # "bump" means elements are bunched up at the ends or the middle of the curve.
30 | # In this case el_distrib_val is smaller than 1, so elements crowd at the edges.
31 | # "progression" means each element along the curve is larger/smaller than the previous one.
32 | # A larger el_distrib_val makes the elements larger at the end of the curves.
33 |
34 | g.spline([0, 1], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
35 | g.spline([1, 2], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1)
36 | g.spline([2, 3], el_on_curve=10, el_distrib_type="bump", el_distrib_val=0.2)
37 | g.spline(
38 | [0, 3], el_on_curve=20, el_distrib_type="progression", el_distrib_val=1.1
39 | ) # Change order of points to reverse progression distribution
40 | g.spline([2, 4, 1])
41 |
42 | # Add Surfaces:
43 | # A structured surface must contain 4 curves that have the parameter 'el_on_curve'
44 | # defined. The number of elements on two opposite curves must be the same
45 | # (In this case, curves 0 & 2 and 1 & 3).
46 |
47 | g.structuredSurface([0, 1, 2, 3])
48 | g.surface([4, 1])
49 |
50 | # ---- Create mesh ----------------------------------------------------------
51 |
52 | mesh = cfm.GmshMesh(g)
53 |
54 | # Element type 3 is quad. (2 is triangle. See user manual for more element types)
55 |
56 | mesh.el_type = 3
57 |
58 | # Degrees of freedom per node.
59 |
60 | mesh.dofs_per_node = 1
61 | mesh.el_size_factor = 0.01
62 |
63 | # mesh.gmsh_exec_path = "D:\\vsmn20-software\\gmsh\gmsh.exe"
64 |
65 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
66 |
67 | # ---- Visualise mesh -------------------------------------------------------
68 |
69 | # Draw geometry
70 |
71 | cfv.draw_geometry(g)
72 |
73 | # Draw mesh
74 |
75 | cfv.figure()
76 | cfv.draw_mesh(
77 | coords, edof, dofs_per_node=mesh.dofs_per_node, el_type=mesh.el_type, filled=True
78 | )
79 |
80 | # Enter main loop
81 |
82 | cfv.show_and_wait()
83 |
--------------------------------------------------------------------------------
/examples/exm_temp_2d_markers.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 07
4 |
5 | Meshing 8-node-isoparametric elements (second order incomplete quads).
6 | Shows use of surfacemarkers/elementmarkers to apply different properties to
7 | elements in different regions.
8 | """
9 |
10 | import calfem.geometry as cfg
11 | import calfem.mesh as cfm
12 | import calfem.vis_mpl as cfv
13 | import calfem.utils as cfu
14 | import calfem.core as cfc
15 |
16 | import matplotlib.pyplot as plt
17 | import matplotlib as mpl
18 | import matplotlib.tri as tri
19 |
20 | import numpy as np
21 |
22 | # ---- Problem constants ----------------------------------------------------
23 |
24 | kx1 = 100
25 | ky1 = 100
26 | kx2 = 10
27 | ky2 = 10
28 | t = 1.0
29 |
30 | # Gauss points or integration points
31 |
32 | n = 2
33 | ep = [t, n]
34 |
35 | D1 = np.matrix([[kx1, 0.0], [0.0, ky1]])
36 | D2 = np.matrix([[kx2, 0.0], [0.0, ky2]])
37 |
38 | # markers 10 & 11 will be used to specify different regions with different
39 | # conductivity.
40 |
41 | Ddict = {10: D1, 11: D2}
42 |
43 | # ---- Create Geometry ------------------------------------------------------
44 |
45 | g = cfg.geometry()
46 |
47 | # Add Points:
48 |
49 | points = [[0, 0], [0, 100], [0, 150], [100, 0], [150, 0], [100, -100], [150, -100]]
50 |
51 | for p in points:
52 | g.point(p)
53 |
54 | # Add Splines:
55 |
56 | g.spline([1, 2], marker=2, el_on_curve=4)
57 | g.spline([3, 4], el_on_curve=4)
58 | g.circle([1, 0, 3], el_on_curve=10)
59 | g.circle([2, 0, 4], el_on_curve=10)
60 | g.spline([3, 5], el_on_curve=6)
61 | g.spline([5, 6], marker=3, el_on_curve=4)
62 | g.spline([6, 4], el_on_curve=6)
63 |
64 | # Add Surfaces:
65 | #
66 | # When we set markers for surfaces, and have 2D elements, we can find which
67 | # region an element is in via the list 'elementmarkers', which is returned by
68 | # GmshMesher.create()
69 |
70 | g.structuredSurface([0, 2, 1, 3], marker=10)
71 | g.structuredSurface([1, 4, 5, 6], marker=11)
72 |
73 | # Element type 16 is 8-node-quad. (See gmsh manual for more element types)
74 |
75 | el_type = 16
76 |
77 | # Degrees of freedom per node.
78 |
79 | dofs_per_node = 1
80 |
81 | # ---- Generate mesh --------------------------------------------------------
82 |
83 | # gmshExecPath = Path to gmsh.exe.
84 | # If None then the system PATH variable is queried.
85 | # Relative and absolute paths work.
86 |
87 | mesh = cfm.GmshMeshGenerator(g, el_type, dofs_per_node)
88 |
89 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
90 |
91 | # ---- Solve problem --------------------------------------------------------
92 |
93 | print("Assembling system matrix...")
94 |
95 | n_dofs = np.size(dofs)
96 | ex, ey = cfc.coordxtr(edof, coords, dofs)
97 |
98 | K = np.zeros([n_dofs, n_dofs])
99 |
100 | for eltopo, elx, ely, elMarker in zip(edof, ex, ey, elementmarkers):
101 | # Calc element stiffness matrix: Conductivity matrix D is taken
102 | # from Ddict and depends on which region (which marker) the element is in.
103 |
104 | Ke = cfc.flw2i8e(elx, ely, ep, Ddict[elMarker])
105 | cfc.assem(eltopo, K, Ke)
106 |
107 | print("Solving equation system...")
108 |
109 | f = np.zeros([n_dofs, 1])
110 |
111 | bc = np.array([], "i")
112 | bc_val = np.array([], "i")
113 |
114 | bc, bc_val = cfu.applybc(bdofs, bc, bc_val, 2, 30.0)
115 | bc, bc_val = cfu.applybc(bdofs, bc, bc_val, 3, 0.0)
116 |
117 | a, r = cfc.solveq(K, f, bc, bc_val)
118 |
119 | # ---- Compute element forces -----------------------------------------------
120 |
121 | print("Computing element forces...")
122 |
123 | ed = cfc.extractEldisp(edof, a)
124 |
125 | for i in range(np.shape(ex)[0]):
126 | es, et, eci = cfc.flw2i8s(
127 | ex[i, :], ey[i, :], ep, Ddict[elementmarkers[i]], ed[i, :]
128 | )
129 |
130 | # Do something with es, et, eci here.
131 |
132 | # ---- Visualise results ----------------------------------------------------
133 |
134 | print("Visualising...")
135 |
136 | cfv.figure()
137 | cfv.draw_geometry(g, title="Geometry")
138 |
139 | # 8-node quads are drawn as simple quads.
140 |
141 | cfv.figure()
142 | cfv.draw_mesh(coords, edof, dofs_per_node, el_type, filled=False)
143 |
144 | cfv.figure()
145 | cfv.draw_nodal_values_shaded(
146 | a,
147 | coords,
148 | edof,
149 | title="Temperature",
150 | dofs_per_node=mesh.dofs_per_node,
151 | el_type=mesh.el_type,
152 | draw_elements=True,
153 | )
154 | cbar = cfv.colorbar(orientation="vertical")
155 | cbar.set_label("Temperature")
156 |
157 |
158 | cfv.text("The bend has high conductivity", (75, 130))
159 | cfv.text("This part has low conductivity", (20, -90))
160 |
161 | # Enter main loop
162 |
163 | cfv.show_and_wait()
164 |
165 | print("Done.")
166 |
--------------------------------------------------------------------------------
/examples/exm_tet_mesh.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 05
4 |
5 | This example shows how to make an unstructured 3D mesh (tetrahedron elements, which calfem cant actually use).
6 | It also demonstrates how to do subplots and create two axes that are viewed from the same camera.
7 | """
8 |
9 | import calfem.geometry as cfg
10 | import calfem.mesh as cfm
11 | import calfem.vis as cfv
12 |
13 | # ---- Define geometry ------------------------------------------------------
14 |
15 | g = cfg.geometry()
16 |
17 | g.point([0, 0, 0], 0)
18 | g.point([1, 0, 0], 1)
19 | g.point([0, 1, 0], 2)
20 | g.point([0, 1, 1], 3, el_size=0.1)
21 | g.point([0.5, -0.3, 0], 4)
22 | g.point([-0.3, 0.5, 0], 5)
23 | g.point([0.75, 0.75, 0], 6)
24 |
25 | g.spline([0, 4, 1])
26 | g.spline([1, 6, 2])
27 | g.spline([2, 5, 0])
28 | g.spline([0, 3])
29 | g.spline([3, 2])
30 | g.spline([3, 1])
31 |
32 | g.ruledSurface([0, 1, 2])
33 | g.ruledSurface([0, 5, 3])
34 | g.ruledSurface([1, 5, 4])
35 | g.ruledSurface([2, 3, 4])
36 |
37 | g.volume([0, 1, 2, 3])
38 |
39 | # ---- Create mesh ----------------------------------------------------------
40 |
41 | # Element type 4 is tetrahedron. (See user manual for more element types).
42 |
43 | el_type = 4
44 |
45 | # Degrees of freedom per node.
46 |
47 | dofs_per_node = 1
48 |
49 | # Create mesh
50 |
51 | coords, edof, dofs, bdofs, elementmarkers = cfm.mesh(g, el_type, 0.3, dofs_per_node)
52 |
53 | # coords, edof, dofs, bdofs, _ = cfm.mesh(
54 | # g, el_type, 0.3, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
55 |
56 |
57 | # ---- Visualise mesh -------------------------------------------------------
58 |
59 | # Create two axes that are viewed from the same camera:
60 |
61 | cfv.figure()
62 | a1 = cfv.subplot(121)
63 | a2 = cfv.subplot(122)
64 | cam = cfv.camera3d()
65 | a1.camera = a2.camera = cam
66 |
67 | # Draw geometry and mesh
68 |
69 | cfv.draw_geometry(g, axes=a1)
70 | cfv.draw_mesh(
71 | coords=coords,
72 | edof=edof,
73 | dofs_per_node=dofs_per_node,
74 | el_type=el_type,
75 | filled=False,
76 | axes=a2,
77 | )
78 |
79 | # Enter main loop
80 |
81 | cfv.show_and_wait()
82 |
--------------------------------------------------------------------------------
/examples/exm_tet_mesh_vtk.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | """Example 05
4 |
5 | This example shows how to make an unstructured 3D mesh (tetrahedron elements, which calfem cant actually use).
6 | It also demonstrates how to do subplots and create two axes that are viewed from the same camera.
7 | """
8 |
9 | import calfem.geometry as cfg
10 | import calfem.mesh as cfm
11 | import calfem.vis_vtk as cfv
12 |
13 | import vtk
14 |
15 | # ---- Define geometry ------------------------------------------------------
16 |
17 | g = cfg.geometry()
18 |
19 | g.point([0, 0, 0], 0)
20 | g.point([1, 0, 0], 1)
21 | g.point([0, 1, 0], 2)
22 | g.point([0, 1, 1], 3, el_size=0.1)
23 | g.point([0.5, -0.3, 0], 4)
24 | g.point([-0.3, 0.5, 0], 5)
25 | g.point([0.75, 0.75, 0], 6)
26 |
27 | g.spline([0, 4, 1])
28 | g.spline([1, 6, 2])
29 | g.spline([2, 5, 0])
30 | g.spline([0, 3])
31 | g.spline([3, 2])
32 | g.spline([3, 1])
33 |
34 | g.ruled_surface([0, 1, 2])
35 | g.ruled_surface([0, 5, 3])
36 | g.ruled_surface([1, 5, 4])
37 | g.ruled_surface([2, 3, 4])
38 |
39 | g.volume([0, 1, 2, 3])
40 |
41 | # ---- Create mesh ----------------------------------------------------------
42 |
43 | # Element type 4 is tetrahedron. (See user manual for more element types).
44 |
45 | el_type = 4
46 |
47 | # Degrees of freedom per node.
48 |
49 | dofs_per_node = 1
50 |
51 | # Create mesh
52 |
53 | coords, edof, dofs, bdofs, elementmarkers = cfm.mesh(g, el_type, 0.3, dofs_per_node)
54 |
55 | # coords, edof, dofs, bdofs, _ = cfm.mesh(
56 | # g, el_type, 0.3, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
57 |
58 |
59 | # ---- Visualise mesh -------------------------------------------------------
60 |
61 | cfv.draw_mesh(coords, edof, el_type)
62 |
--------------------------------------------------------------------------------
/examples/exm_tutorial_1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Sat Mar 3 22:08:29 2018
4 |
5 | @author: Jonas Lindemann
6 | """
7 |
8 | import calfem.geometry as cfg
9 | import calfem.mesh as cfm
10 | import calfem.vis_mpl as cfv
11 |
12 | # ----- Define geometry
13 |
14 | g = cfg.Geometry()
15 |
16 | g.point([0.0, 0.0]) # point 0
17 | g.point([5.0, 0.0], marker=20) # point 1
18 | g.point([2.5, 4.0]) # point 2
19 |
20 | g.spline([0, 1]) # line 0
21 | g.spline([1, 2]) # line 1
22 | g.spline([2, 0], marker=10) # line 2
23 |
24 | g.surface([0, 1, 2])
25 |
26 | # ----- Create mesh
27 |
28 | mesh = cfm.GmshMesh(g)
29 |
30 | mesh.el_type = 2 # Degrees of freedom per node.
31 | mesh.dofs_per_node = 1 # Factor that changes element sizes.
32 | mesh.el_size_factor = 0.15
33 |
34 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
35 |
36 | print(bdofs)
37 |
38 | cfv.figure()
39 | cfv.draw_geometry(g)
40 |
41 | # ----- Draw the mesh.
42 |
43 | cfv.figure()
44 | cfv.draw_mesh(
45 | coords=coords,
46 | edof=edof,
47 | dofs_per_node=mesh.dofsPerNode,
48 | el_type=mesh.elType,
49 | filled=True,
50 | title="Example 01",
51 | )
52 |
53 | cfv.showAndWait()
54 |
--------------------------------------------------------------------------------
/examples/exm_tutorial_2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Sat Mar 3 22:08:29 2018
4 |
5 | @author: Jonas Lindemann
6 | """
7 |
8 | import calfem.core as cfc
9 | import calfem.geometry as cfg
10 | import calfem.mesh as cfm
11 | import calfem.vis_mpl as cfv
12 | import calfem.utils as cfu
13 |
14 | import numpy as np
15 | from math import *
16 |
17 | # ----- Problem parameters
18 |
19 | l = 5.0
20 | h = 1.0
21 | t = 0.2
22 |
23 | v = 0.35
24 | E = 2.1e9
25 | ptype = 1
26 | ep = [ptype, t]
27 | D = cfc.hooke(ptype, E, v)
28 |
29 | left_support = 10
30 | right_support = 20
31 | top_line = 30
32 |
33 | # ----- Define geometry
34 |
35 | g = cfg.Geometry()
36 |
37 | g.point([0.0, 0.0], marker=left_support) # point 0
38 | g.point([l, 0.0], marker=right_support) # point 1
39 | g.point([l, h]) # point 2
40 | g.point([0.0, h]) # point 2
41 |
42 | g.spline([0, 1]) # line 0
43 | g.spline([1, 2]) # line 1
44 | g.spline([2, 3], marker=top_line) # line 2
45 | g.spline([3, 0]) # line 2
46 |
47 | g.surface([0, 1, 2, 3])
48 |
49 | # ----- Create mesh
50 |
51 | mesh = cfm.GmshMesh(g)
52 |
53 | mesh.el_type = 3 # Degrees of freedom per node.
54 | mesh.dofs_per_node = 2 # Factor that changes element sizes.
55 | mesh.el_size_factor = 0.10
56 |
57 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
58 |
59 | # ----- Solve problem
60 |
61 | nDofs = np.size(dofs)
62 | ex, ey = cfc.coordxtr(edof, coords, dofs)
63 |
64 | K = np.zeros([nDofs, nDofs])
65 |
66 | for eltopo, elx, ely in zip(edof, ex, ey):
67 | Ke = cfc.planqe(elx, ely, ep, D)
68 | cfc.assem(eltopo, K, Ke)
69 |
70 | bc = np.array([], "i")
71 | bcVal = np.array([], "f")
72 |
73 | bc, bcVal = cfu.applybc(bdofs, bc, bcVal, left_support, 0.0, 0)
74 | bc, bcVal = cfu.applybc(bdofs, bc, bcVal, right_support, 0.0, 2)
75 |
76 | f = np.zeros([nDofs, 1])
77 |
78 | cfu.applyforcetotal(bdofs, f, top_line, -10e5, 2)
79 |
80 | a, r = cfc.solveq(K, f, bc, bcVal)
81 |
82 | ed = cfc.extract_eldisp(edof, a)
83 | vonMises = []
84 |
85 | for i in range(edof.shape[0]):
86 | es, et = cfc.planqs(ex[i, :], ey[i, :], ep, D, ed[i, :])
87 | vonMises.append(sqrt(pow(es[0], 2) - es[0] * es[1] + pow(es[1], 2) + 3 * es[2]))
88 |
89 | # ----- Draw geometry
90 |
91 | cfv.figure()
92 | cfv.draw_geometry(g)
93 |
94 | # ----- Draw the mesh.
95 |
96 | cfv.figure()
97 | cfv.draw_mesh(
98 | coords=coords,
99 | edof=edof,
100 | dofs_per_node=mesh.dofs_per_node,
101 | el_type=mesh.el_type,
102 | filled=True,
103 | title="Example 01",
104 | )
105 |
106 | # ----- Draw results
107 |
108 | cfv.figure()
109 | cfv.draw_element_values(
110 | vonMises,
111 | coords,
112 | edof,
113 | mesh.dofs_per_node,
114 | mesh.el_type,
115 | a,
116 | draw_elements=True,
117 | draw_undisplaced_mesh=False,
118 | title="Example 06 effective stress",
119 | )
120 |
121 | cfv.figure()
122 | cfv.draw_displacements(
123 | a,
124 | coords,
125 | edof,
126 | mesh.dofs_per_node,
127 | mesh.el_type,
128 | draw_undisplaced_mesh=True,
129 | title="Example 06",
130 | magnfac=10.0,
131 | )
132 |
133 | cfv.showAndWait()
134 |
--------------------------------------------------------------------------------
/examples/exn_bar2g.py:
--------------------------------------------------------------------------------
1 | # example exn_bar2g
2 | # --------------------------------------------------------------------------
3 | # PURPOSE
4 | # Analysis of a plane truss using second order theory.
5 | # --------------------------------------------------------------------------
6 |
7 | import numpy as np
8 | import calfem.core as cfc
9 | import calfem.utils as cfu
10 |
11 | # ----- Topology -----
12 |
13 | edof = np.array([[1, 2, 5, 6], [3, 4, 5, 6]])
14 |
15 | # ----- Element properties and global coordinates -------------------------
16 |
17 | E = 10e9
18 | A1 = 4e-2
19 | A2 = 1e-2
20 | ep1 = np.array([E, A1])
21 | ep2 = np.array([E, A2])
22 |
23 | ex1 = np.array([0.0, 1.6])
24 | ey1 = np.array([0.0, 0.0])
25 | ex2 = np.array([0.0, 1.6])
26 | ey2 = np.array([1.2, 0])
27 |
28 | # ----- Initial values for the iteration ----------------------------------
29 |
30 | eps = 1e-6 # Error norm
31 | QX1 = 0.01
32 | QX2 = 0
33 | # Initial axial forces
34 | QX01 = 1 # Axial force of the initial former iteration
35 | n = 0 # Iteration counter
36 |
37 | # ----- Iteration procedure -----------------------------------------------
38 | while abs((QX1 - QX01) / QX01) > eps:
39 | n += 1
40 |
41 | K = np.zeros((6, 6))
42 | f = np.zeros((6, 1))
43 | f[4] = -10e6
44 | f[5] = -0.2e6
45 |
46 | Ke1 = cfc.bar2ge(ex1, ey1, ep1, QX1)
47 | Ke2 = cfc.bar2ge(ex2, ey2, ep2, QX2)
48 | K = cfc.assem(edof[0, :], K, Ke1)
49 | K = cfc.assem(edof[1, :], K, Ke2)
50 | bc = np.array([1, 2, 3, 4])
51 | a, r = cfc.solveq(K, f, bc)
52 |
53 | Ed = cfc.extract_ed(edof, a)
54 |
55 | QX01 = QX1
56 | es1, QX1 = cfc.bar2gs(ex1, ey1, ep1, Ed[0, :])
57 | es2, QX2 = cfc.bar2gs(ex2, ey2, ep2, Ed[1, :])
58 |
59 | if n > 20:
60 | print("The solution does not converge")
61 | break
62 |
63 | # ----- Results -----------------------------------------------
64 |
65 | cfu.disp_h1("Displacements:")
66 | cfu.disp_array(a)
67 | cfu.disp_h1("Normal forces:")
68 | cfu.disp(QX1)
69 | cfu.disp(QX2)
70 |
--------------------------------------------------------------------------------
/examples/exn_bar2m.py:
--------------------------------------------------------------------------------
1 | # example exn_bar2m
2 | # --------------------------------------------------------------------------
3 | # PURPOSE
4 | # Analysis of a plane truss considering material nonlinearity.
5 | # --------------------------------------------------------------------------
6 |
7 | import numpy as np
8 | import calfem.core as cfc
9 | import calfem.utils as cfu
10 | import calfem.vis_mpl as cfv
11 |
12 | edof = np.array([
13 | [1, 2, 5, 6],
14 | [5, 6, 7, 8],
15 | [3, 4, 5, 6]
16 | ])
17 |
18 | bc = np.array([1, 2, 3, 4, 7, 8])
19 |
20 | ex = np.array([
21 | [0.0, 1.6],
22 | [1.6, 1.6],
23 | [0.0, 1.6]
24 | ])
25 |
26 | ey = np.array([[0.0, 0.0], [0.0, 1.2], [1.2, 0.0]])
27 |
28 | E = np.array([200e9, 200e9, 200e9])
29 | A = np.array([6.0e-4, 3.0e-4, 10.0e-4])
30 | SY = 400e6
31 | Ns = (SY * A).reshape(-1, 1)
32 |
33 | dp = 4e3
34 |
35 | incr = 100
36 |
37 | a = np.zeros((8, 1))
38 | r = np.zeros((8, 1))
39 | es = np.zeros((3, 1))
40 |
41 | plbar = 0
42 | pl = np.array([0.0, 0.0])
43 |
44 | # Forward Euler increamental solution
45 |
46 | for i in range(incr):
47 | K = np.zeros((8, 8))
48 | df = np.zeros((8, 1))
49 | df[5] = -dp
50 |
51 | # Create and assemble element tangent stiffness matrix
52 |
53 | for j in range(3):
54 | ep = np.array([E[j], A[j]])
55 | Ke = cfc.bar2e(ex[j, :], ey[j, :], ep)
56 | K = cfc.assem(edof[j, :], K, Ke)
57 |
58 | # Stop iteration if determinant det(Kr) <= 0
59 |
60 | fdof = np.setdiff1d(np.arange(1, 9), bc) - 1
61 | Kr = K[np.ix_(fdof, fdof)]
62 | if np.linalg.det(Kr) <= 0:
63 | print("Determinant zero after increment ", i)
64 | break
65 |
66 | # Solve for the displacement increment and determine total displacements
67 |
68 | da, dr = cfc.solveq(K, df, bc)
69 | a += da
70 | r += dr
71 |
72 | # Determine normal forces in elements
73 |
74 | ded = cfc.extract_ed(edof, da)
75 | des = np.zeros((3, 1))
76 |
77 | for j in range(3):
78 | ep = np.array([E[j], A[j]])
79 | desj = cfc.bar2s(ex[j, :], ey[j, :], ep, ded[j, :])
80 | des[j, 0] = desj[0]
81 |
82 | es += des
83 |
84 | for j in range(3):
85 | if abs(es[j, 0]) >= Ns[j]:
86 | E[j] = 0
87 |
88 | # Determine if the stress in a bar has reached the yield stress
89 |
90 | newplbar = np.sum(abs(es) > Ns)
91 |
92 | if newplbar > plbar:
93 | plbar = newplbar
94 | print(
95 | plbar, "plastic elements for increment ", i + 1, " at load = ", (i + 1) * dp
96 | )
97 |
98 | # Save variables for curve plotting
99 |
100 | pl = np.vstack((pl, np.array([-a[5, 0], (i + 1) * dp])))
101 |
102 | # Plot force-displacement relation
103 |
104 | cfv.figure(1, fig_size=(7, 4))
105 | cfv.plt.plot(pl[:, 0], pl[:, 1])
106 | cfv.plt.xlabel("Displacement")
107 | cfv.plt.ylabel("Force")
108 | cfv.show_and_wait()
109 |
--------------------------------------------------------------------------------
/examples/exn_beam2.py:
--------------------------------------------------------------------------------
1 | # example exn_beam2g
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Geometrically nonlinear analysis of a plane frame.
5 | # ----------------------------------------------------------------
6 |
7 | import numpy as np
8 | import calfem.core as cfc
9 | import calfem.vis_mpl as cfv
10 |
11 |
12 | # ----- Topology -------------------------------------------------
13 |
14 | edof = np.array([
15 | [4, 5, 6, 1, 2, 3],
16 | [7, 8, 9, 10, 11, 12],
17 | [4, 5, 6, 7, 8, 9]
18 | ])
19 |
20 | # ----- Element stiffness and element load matrices -------------
21 |
22 | E = 200e9
23 | A1 = 2e-3
24 | A2 = 6e-3
25 | I1 = 1.6e-5
26 | I2 = 5.4e-5
27 |
28 | ep1 = np.array([E, A1, I1])
29 | ep3 = np.array([E, A2, I2])
30 |
31 | ex1 = np.array([0.0, 0.0])
32 | ey1 = np.array([4.0, 0.0])
33 | ex2 = np.array([6.0, 6.0])
34 | ey2 = np.array([4.0, 0.0])
35 | ex3 = np.array([0.0, 6.0])
36 | ey3 = np.array([4.0, 4.0])
37 |
38 | eq1 = np.array([0.0])
39 | eq2 = np.array([0.0])
40 | eq3 = np.array([-50e3])
41 |
42 | # ----- Initial axial forces ----------------------------------------------
43 |
44 | QX1 = 1e-4
45 | QX2 = 0
46 | QX3 = 0
47 | QX01 = 1
48 |
49 | # ----- Iteration for convergence -----------------------------------------
50 |
51 | eps = 1e-6
52 | n = 0
53 |
54 | while abs((QX1 - QX01) / QX01) > eps:
55 | n += 1
56 | K = np.zeros([12, 12])
57 | f = np.zeros([12, 1])
58 | f[3, 0] = 10e3
59 |
60 | Ke1 = cfc.beam2ge(ex1, ey1, ep1, QX1)
61 | Ke2 = cfc.beam2ge(ex2, ey2, ep1, QX2)
62 | Ke3, fe3 = cfc.beam2ge(ex3, ey3, ep3, QX3, eq3)
63 |
64 | K = cfc.assem(edof[0, :], K, Ke1)
65 | K = cfc.assem(edof[1, :], K, Ke2)
66 | K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)
67 |
68 | bc = np.array([1, 2, 3, 10, 11])
69 | a, r = cfc.solveq(K, f, bc)
70 |
71 | ed = cfc.extract_ed(edof, a)
72 |
73 | QX01 = QX1
74 | es1 = cfc.beam2gs(ex1, ey1, ep1, ed[0, :], QX1, eq1)
75 | es2 = cfc.beam2gs(ex2, ey2, ep1, ed[1, :], QX2, eq2)
76 | es3 = cfc.beam2gs(ex3, ey3, ep3, ed[2, :], QX3, eq3)
77 | QX1 = es1[1]
78 | QX2 = es2[1]
79 | QX3 = es3[1]
80 |
81 | if n == 1:
82 | ed0 = ed
83 |
84 | if n > 20:
85 | print("The solution does not converge")
86 | break
87 |
88 |
89 | # ----- Section forces ---------------------------------------
90 |
91 | eq1 = np.array([0.0, eq1.item()])
92 | eq2 = np.array([0.0, eq2.item()])
93 | eq3 = np.array([0.0, eq3.item()])
94 | es1, edi1, eci1 = cfc.beam2s(ex1, ey1, ep1, ed[0, :], eq1, 21)
95 | es2, edi2, eci2 = cfc.beam2s(ex2, ey2, ep1, ed[1, :], eq2, 21)
96 | es3, edi3, eci3 = cfc.beam2s(ex3, ey3, ep3, ed[2, :], eq3, 21)
97 |
98 |
99 | # ----- Draw deformed frame ---------------------------------------
100 |
101 | cfv.figure(1, fig_size=(6, 4))
102 | plotpar = [3, 1, 0]
103 | cfv.eldraw2(ex1, ey1, plotpar)
104 | cfv.eldraw2(ex2, ey2, plotpar)
105 | cfv.eldraw2(ex3, ey3, plotpar)
106 | sfac = cfv.scalfact2(ex3, ey3, edi3, 0.1)
107 | plotpar = [1, 2, 1]
108 | cfv.eldisp2(ex1, ey1, ed[0, :], plotpar, sfac)
109 | cfv.eldisp2(ex2, ey2, ed[1, :], plotpar, sfac)
110 | cfv.eldisp2(ex3, ey3, ed[2, :], plotpar, sfac)
111 | plotpar = [2, 4, 2]
112 | cfv.eldisp2(ex1, ey1, ed0[0, :], plotpar, sfac)
113 | cfv.eldisp2(ex2, ey2, ed0[1, :], plotpar, sfac)
114 | cfv.eldisp2(ex3, ey3, ed0[2, :], plotpar, sfac)
115 | cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
116 | cfv.title("Displacements")
117 |
118 |
119 | # ----- Draw normal force diagram --------------------------------
120 | cfv.figure(2, fig_size=(6, 4))
121 | plotpar = [2, 1]
122 | sfac = cfv.scalfact2(ex1, ey1, es1[:, 0], 0.2)
123 | cfv.secforce2(ex1, ey1, es1[:, 0], plotpar, sfac)
124 | cfv.secforce2(ex2, ey2, es2[:, 0], plotpar, sfac)
125 | cfv.secforce2(ex3, ey3, es3[:, 0], plotpar, sfac)
126 | cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
127 | cfv.title("Normal force")
128 |
129 | # ----- Draw shear force diagram ---------------------------------
130 | cfv.figure(3, fig_size=(6, 4))
131 | plotpar = [2, 1]
132 | sfac = cfv.scalfact2(ex3, ey3, es3[:, 1], 0.2)
133 | cfv.secforce2(ex1, ey1, es1[:, 1], plotpar, sfac)
134 | cfv.secforce2(ex2, ey2, es2[:, 1], plotpar, sfac)
135 | cfv.secforce2(ex3, ey3, es3[:, 1], plotpar, sfac)
136 | cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
137 | cfv.title("Shear force")
138 |
139 | # ----- Draw moment diagram --------------------------------------
140 | cfv.figure(4, fig_size=(6, 4))
141 | plotpar = [2, 1]
142 | sfac = cfv.scalfact2(ex3, ey3, es3[:, 2], 0.2)
143 | cfv.secforce2(ex1, ey1, es1[:, 2], plotpar, sfac)
144 | cfv.secforce2(ex2, ey2, es2[:, 2], plotpar, sfac)
145 | cfv.secforce2(ex3, ey3, es3[:, 2], plotpar, sfac)
146 | cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
147 | cfv.title("Bending moment")
148 | cfv.show_and_wait()
149 | # ------------------------ end -----------------------------------
150 |
--------------------------------------------------------------------------------
/examples/exn_beam2_b.py:
--------------------------------------------------------------------------------
1 | # example exn_beam2g_b
2 | # ----------------------------------------------------------------
3 | # PURPOSE
4 | # Buckling analysis of a plane frame.
5 | # ----------------------------------------------------------------
6 |
7 | import numpy as np
8 | import calfem.core as cfc
9 | import calfem.vis_mpl as cfv
10 |
11 |
12 | # ----- Topology -------------------------------------------------
13 |
14 | edof = np.array([[4, 5, 6, 1, 2, 3], [7, 8, 9, 10, 11, 12], [4, 5, 6, 7, 8, 9]])
15 |
16 | # ----- Element stiffness and element load matrices -------------
17 |
18 | E = 200e9
19 | A1 = 2e-3
20 | A2 = 6e-3
21 | I1 = 1.6e-5
22 | I2 = 5.4e-5
23 |
24 | ep1 = np.array([E, A1, I1])
25 | ep3 = np.array([E, A2, I2])
26 |
27 | ex1 = np.array([0.0, 0.0])
28 | ey1 = np.array([4.0, 0.0])
29 | ex2 = np.array([6.0, 6.0])
30 | ey2 = np.array([4.0, 0.0])
31 | ex3 = np.array([0.0, 6.0])
32 | ey3 = np.array([4.0, 4.0])
33 |
34 | eq1 = np.array([0.0])
35 | eq2 = np.array([0.0])
36 | eq3 = np.array([-50e3])
37 |
38 | # ----- Initial axial forces ----------------------------------------------
39 |
40 | QX1 = 1e-4
41 | QX2 = 0
42 | QX3 = 0
43 | QX01 = 1
44 |
45 | # ----- Iteration for convergence -----------------------------------------
46 |
47 | eps = 1e-6
48 | n = 0
49 |
50 | while abs((QX1 - QX01) / QX01) > eps:
51 | n += 1
52 | K = np.zeros([12, 12])
53 | f = np.zeros([12, 1])
54 | f[3, 0] = 10e3
55 |
56 | Ke1 = cfc.beam2ge(ex1, ey1, ep1, QX1)
57 | Ke2 = cfc.beam2ge(ex2, ey2, ep1, QX2)
58 | Ke3, fe3 = cfc.beam2ge(ex3, ey3, ep3, QX3, eq3)
59 |
60 | K = cfc.assem(edof[0, :], K, Ke1)
61 | K = cfc.assem(edof[1, :], K, Ke2)
62 | K, f = cfc.assem(edof[2, :], K, Ke3, f, fe3)
63 | if n == 1:
64 | K0 = K
65 |
66 | bc = np.array([1, 2, 3, 10, 11])
67 | a, r = cfc.solveq(K, f, bc)
68 |
69 | ed = cfc.extract_ed(edof, a)
70 |
71 | QX01 = QX1
72 | es1 = cfc.beam2gs(ex1, ey1, ep1, ed[0, :], QX1, eq1)
73 | es2 = cfc.beam2gs(ex2, ey2, ep1, ed[1, :], QX2, eq2)
74 | es3 = cfc.beam2gs(ex3, ey3, ep3, ed[2, :], QX3, eq3)
75 |
76 | QX1 = es1[1]
77 | QX2 = es2[1]
78 | QX3 = es3[1]
79 |
80 | if n > 20:
81 | print("The solution does not converge")
82 | break
83 |
84 |
85 | # ----- Buckling analysis -------------------------------------------------
86 |
87 | lam, phi = cfc.eigen(K, K0, bc)
88 | one = np.ones(lam.shape)
89 | alpha = np.divide(one, one - lam)
90 | print(alpha[0])
91 |
92 | # ----- Draw shape at instability -----------------------------------------
93 |
94 | Ed = cfc.extract_ed(edof, -phi[:, 0])
95 | cfv.figure(1, fig_size=(6, 4))
96 | plotpar = [3, 1, 0]
97 | cfv.eldraw2(ex1, ey1, plotpar)
98 | cfv.eldraw2(ex2, ey2, plotpar)
99 | cfv.eldraw2(ex3, ey3, plotpar)
100 | sfac = cfv.scalfact2(ex3, ey3, Ed[2, :], 0.1)
101 | plotpar = [1, 2, 1]
102 | cfv.eldisp2(ex1, ey1, Ed[0, :], plotpar, sfac)
103 | cfv.eldisp2(ex2, ey2, Ed[1, :], plotpar, sfac)
104 | cfv.eldisp2(ex3, ey3, Ed[2, :], plotpar, sfac)
105 | cfv.plt.axis([-1.5, 7.5, -0.5, 5.5])
106 | cfv.title("Shape at instability")
107 | cfv.show_and_wait()
108 |
109 | # ------------------------ end -----------------------------------
110 |
--------------------------------------------------------------------------------
/examples/experimental/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "python.pythonPath": "e:\\anaconda3\\python.exe"
3 | }
--------------------------------------------------------------------------------
/examples/experimental/exed1.ui:
--------------------------------------------------------------------------------
1 |
2 |
3 | MainWindow
4 |
5 |
6 |
7 | 0
8 | 0
9 | 800
10 | 600
11 |
12 |
13 |
14 | MainWindow
15 |
16 |
17 |
18 | -
19 |
20 |
21 |
22 |
23 |
33 |
34 |
35 |
36 |
37 |
38 |
--------------------------------------------------------------------------------
/examples/experimental/exint1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import calfem.intvis as iv
4 |
5 | # --- Parametrar som kan ändras
6 |
7 | a = 1
8 | b_slider = 2.0
9 | c_list = [1, 2, 3]
10 | d_check = True
11 | f_param = 42.0
12 | g_float = 84.0
13 | g_int = 34
14 |
15 | # --- Redigera parametrar interaktivt
16 |
17 | iv.edit_params(vars())
18 |
19 | def test():
20 | c = 1
21 | d = 2
22 | iv.edit_params(vars())
23 |
24 | test()
25 |
26 | # --- Redigera geometri
27 |
28 | #iv.edit_geometry(g)
29 |
30 |
--------------------------------------------------------------------------------
/examples/experimental/exm11.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Example 10
4 |
5 | The use case from the user manual.
6 | The example does not contain anything that is not covered in the previous examples.
7 | '''
8 |
9 | import calfem.core as cfc
10 | import calfem.vis as cfv
11 | import calfem.utils as cfu
12 | import calfem.shapes as cfs
13 | import calfem.solver as cfslv
14 |
15 | cfu.enableLogging()
16 |
17 | # ---- General parameters ---------------------------------------------------
18 |
19 | # Define marker constants instead of using numbers in the code
20 |
21 | cfu.info("Creating rectangle")
22 |
23 | rect = cfs.Rectangle(5.0, 1.0, element_type=3, dofs_per_node=2, max_area=0.08)
24 | rect.t = 0.2
25 | rect.v = 0.35
26 | rect.E = 2e9
27 | rect.ptype = 1
28 | rect.ep = [rect.ptype, rect.t]
29 | rect.D = cfc.hooke(rect.ptype, rect.E, rect.v)
30 |
31 | cfu.info("Creating mesh...")
32 |
33 | mesh = cfs.ShapeMesh(rect)
34 |
35 | # ---- Solve problem --------------------------------------------------------
36 |
37 | solver = cfslv.Plan2DSolver(mesh)
38 |
39 | solver.addBC(rect.left_id, 0.0)
40 | solver.addForceTotal(rect.top_id, -10e5, dimension=2)
41 |
42 | results = solver.execute()
43 |
44 | # ---- Visualise results ----------------------------------------------------
45 |
46 | cfu.info("Drawing results...")
47 |
48 | cfv.figure()
49 | cfv.draw_geometry(rect.geometry(), title="Geometry")
50 |
51 | cfv.figure()
52 | cfv.draw_mesh(mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
53 | filled=True, title="Mesh") #Draws the mesh.
54 |
55 | cfv.figure()
56 | cfv.draw_displacements(results.a, mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
57 | draw_undisplaced_mesh=False, title="Displacements",
58 | magnfac=1)
59 |
60 | cfv.figure()
61 | cfv.draw_element_values(results.el_forces, mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type, results.a,
62 | draw_elements=True, draw_undisplaced_mesh=False,
63 | title="Effective Stress", magnfac=1)
64 |
65 | #cfv.colorBar().SetLabel("Effective stress")
66 |
67 | cfu.info("Done drawing...")
68 |
69 | cfv.show_and_wait()
--------------------------------------------------------------------------------
/examples/experimental/exm11_mpl.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Example 10
4 |
5 | The use case from the user manual.
6 | The example does not contain anything that is not covered in the previous examples.
7 | '''
8 |
9 | import calfem.core as cfc
10 | import calfem.vis_mpl as cfv
11 | import calfem.utils as cfu
12 | import calfem.shapes as cfs
13 | import calfem.solver as cfslv
14 |
15 | cfu.enableLogging()
16 |
17 | # ---- General parameters ---------------------------------------------------
18 |
19 | # Define marker constants instead of using numbers in the code
20 |
21 | cfu.info("Creating rectangle")
22 |
23 | rect = cfs.Rectangle(5.0, 1.0, element_type=3, dofs_per_node=2, max_area=0.08)
24 | rect.t = 0.2
25 | rect.v = 0.35
26 | rect.E = 2e9
27 | rect.ptype = 1
28 | rect.ep = [rect.ptype, rect.t]
29 | rect.D = cfc.hooke(rect.ptype, rect.E, rect.v)
30 |
31 | cfu.info("Creating mesh...")
32 |
33 | mesh = cfs.ShapeMesh(rect)
34 |
35 | # ---- Solve problem --------------------------------------------------------
36 |
37 | solver = cfslv.Plan2DSolver(mesh)
38 |
39 | solver.addBC(rect.left_id, 0.0)
40 | solver.addForceTotal(rect.top_id, -10e5, dimension=2)
41 |
42 | results = solver.execute()
43 |
44 | # ---- Visualise results ----------------------------------------------------
45 |
46 | cfu.info("Drawing results...")
47 |
48 | cfv.figure()
49 | cfv.draw_geometry(rect.geometry(), title="Geometry")
50 |
51 | cfv.figure()
52 | cfv.draw_mesh(mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
53 | filled=True, title="Mesh") #Draws the mesh.
54 |
55 | cfv.figure()
56 | cfv.draw_displacements(results.a, mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
57 | draw_undisplaced_mesh=False, title="Displacements",
58 | magnfac=1)
59 |
60 | cfv.figure()
61 | cfv.draw_element_values(results.el_forces, mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type, results.a,
62 | draw_elements=True, draw_undisplaced_mesh=False,
63 | title="Effective Stress", magnfac=1)
64 |
65 | #cfv.colorBar().SetLabel("Effective stress")
66 |
67 | cfu.info("Done drawing...")
68 |
69 | cfv.show_and_wait()
--------------------------------------------------------------------------------
/examples/experimental/exm12.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Example 10
4 |
5 | The use case from the user manual.
6 | The example does not contain anything that is not covered in the previous examples.
7 | '''
8 |
9 | import calfem.core as cfc
10 | import calfem.vis as cfv
11 | import calfem.utils as cfu
12 | import calfem.shapes as cfs
13 | import calfem.solver as cfslv
14 |
15 | import numpy as np
16 |
17 | cfu.enableLogging()
18 |
19 | # ---- General parameters ---------------------------------------------------
20 |
21 | # Define marker constants instead of using numbers in the code
22 |
23 | cfu.info("Creating rectangle")
24 |
25 | rect = cfs.Rectangle(5.0, 1.0, element_type=3, dofs_per_node=1, max_area=0.08)
26 |
27 | rect.t = 1
28 | rect.ep = [rect.t, 1]
29 |
30 | rect.D = np.diag([1.7, 1.7])
31 |
32 | cfu.info("Creating mesh...")
33 |
34 | mesh = cfs.ShapeMesh(rect)
35 |
36 | # ---- Solve problem --------------------------------------------------------
37 |
38 | solver = cfslv.Flow2DSolver(mesh)
39 |
40 | solver.addBC(rect.left_id, 0.0)
41 | solver.addBC(rect.right_id, 120.0)
42 | #solver.addForceTotal(rect.topId, -10e5, dimension=2)
43 |
44 | results = solver.execute()
45 |
46 | # ---- Visualise results ----------------------------------------------------
47 |
48 | cfu.info("Drawing results...")
49 |
50 | cfv.figure()
51 | cfv.drawGeometry(rect.geometry(), title="Geometry")
52 |
53 | cfv.figure()
54 | cfv.drawMesh(mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
55 | filled=True, title="Mesh") #Draws the mesh.
56 |
57 | cfv.figure()
58 | cfv.drawNodalValues(results.a, mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type)
59 |
60 | cfv.showAndWait()
--------------------------------------------------------------------------------
/examples/experimental/exm12_mpl.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Example 10
4 |
5 | The use case from the user manual.
6 | The example does not contain anything that is not covered in the previous examples.
7 | '''
8 |
9 | import calfem.core as cfc
10 | import calfem.vis_mpl as cfv
11 | import calfem.utils as cfu
12 | import calfem.shapes as cfs
13 | import calfem.solver as cfslv
14 |
15 | import numpy as np
16 |
17 | import matplotlib.pyplot as plt
18 |
19 | cfu.enableLogging()
20 |
21 | # ---- General parameters ---------------------------------------------------
22 |
23 | # Define marker constants instead of using numbers in the code
24 |
25 | cfu.info("Creating rectangle")
26 |
27 | rect = cfs.Rectangle(5.0, 1.0, element_type=2, dofs_per_node=1, max_area=0.08)
28 |
29 | rect.t = 1
30 | rect.ep = [rect.t, 1]
31 |
32 | rect.D = np.diag([1.7, 1.7])
33 |
34 | cfu.info("Creating mesh...")
35 |
36 | mesh = cfs.ShapeMesh(rect)
37 |
38 | # ---- Solve problem --------------------------------------------------------
39 |
40 | solver = cfslv.Flow2DSolver(mesh)
41 |
42 | solver.addBC(rect.left_id, 0.0)
43 | solver.addBC(rect.right_id, 120.0)
44 | #solver.addForceTotal(rect.topId, -10e5, dimension=2)
45 |
46 | results = solver.execute()
47 |
48 | # ---- Visualise results ----------------------------------------------------
49 |
50 | cfu.info("Drawing results...")
51 |
52 | cfv.figure()
53 | cfv.draw_geometry(rect.geometry(), title="Geometry")
54 |
55 | cfv.figure()
56 | cfv.draw_mesh(mesh.coords, mesh.edof, rect.dofs_per_node, rect.element_type,
57 | filled=True, title="Mesh") #Draws the mesh.
58 |
59 | cfv.figure()
60 | cfv.draw_nodal_values_shaded(results.a, mesh.coords, mesh.edof)
61 | cfv.colorbar()
62 |
63 | cfv.figure()
64 | cfv.draw_nodal_values_contourf(results.a, mesh.coords, mesh.edof)
65 | cfv.colorbar()
66 |
67 | cfv.showAndWait()
--------------------------------------------------------------------------------
/examples/experimental/exm14_vtk.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''Example 05
4 |
5 | This example shows how to make an unstructured 3D mesh (tetrahedron elements, which calfem cant actually use).
6 | It also demonstrates how to do subplots and create two axes that are viewed from the same camera.
7 | '''
8 |
9 | import calfem.geometry as cfg
10 | import calfem.mesh as cfm
11 | import calfem.vis_vtk as cfv
12 |
13 | import prim3d as p3
14 |
15 | import vtk
16 |
17 | # ---- Define geometry ------------------------------------------------------
18 |
19 | #box1 = p3.Box(0.0, 0.0, 0.0)
20 | #box2 = p3.Box(1.0, 0.0, 0.0)
21 |
22 | #model = p3.GeometryModel()
23 | #model.add_volume(box1.volume)
24 | #model.add_volume(box2.volume)
25 |
26 | g = cfg.Geometry()
27 |
28 | # ---- Create mesh ----------------------------------------------------------
29 |
30 | # Element type 4 is tetrahedron. (See user manual for more element types).
31 |
32 | el_type = 5
33 |
34 | # Degrees of freedom per node.
35 |
36 | dofs_per_node = 1
37 |
38 | # Create mesh
39 |
40 | mesh_generator = cfm.GmshMesh("test.geo", el_type, 0.05, dofs_per_node)
41 | mesh_generator.mesh_dir = "mesh"
42 |
43 | mesh_generator.gmsh_options = {"Mesh.Algorithm":6, "Mesh.Algorithm3D":1, "Mesh.RecombinationAlgorithm":1,
44 | "Mesh.RecombineAll":1, "Mesh.Tetrahedra":1}
45 |
46 | coords, edof, dofs, bdofs, elementmarkers = mesh_generator.create(is3D=True)
47 |
48 | #coords, edof, dofs, bdofs, elementmarkers = cfm.mesh(model.geometry, el_type, 0.3, dofs_per_node)
49 |
50 | print(coords)
51 | print(edof)
52 | #print(bdofs)
53 | #print(elementmarkers)
54 |
55 | #print(bdofs[100])
56 | #print(edof[0])
57 |
58 | #coords, edof, dofs, bdofs, _ = cfm.mesh(
59 | # g, el_type, 0.3, dofs_per_node, gmsh_exec_path="D:\\vsmn20-software\\gmsh\gmsh.exe")
60 |
61 |
62 | # ---- Visualise mesh -------------------------------------------------------
63 |
64 | cfv.draw_mesh(coords, edof, el_type)
--------------------------------------------------------------------------------
/examples/experimental/exs6.py:
--------------------------------------------------------------------------------
1 | # example exs6
2 | #----------------------------------------------------------------
3 | # PURPOSE
4 | # Analysis of a plane frame.
5 | #----------------------------------------------------------------
6 |
7 | # REFERENCES
8 | # G"oran Sandberg 94-03-08
9 | # Karl-Gunnar Olsson 95-09-28
10 | # Anders Olsson 99-03-01
11 | # Ola Dahlblom 2004-09-14
12 | #----------------------------------------------------------------
13 |
14 | import numpy as np
15 | import calfem.core as cfc
16 | import calfem.utils as cfu
17 | import calfem.vis_mpl as cfv
18 |
19 | # ----- Topology -------------------------------------------------
20 |
21 | Edof = np.array([
22 | [4, 5, 6, 1, 2, 3],
23 | [7, 8, 9, 10, 11, 12],
24 | [4, 5, 6, 7, 8, 9]
25 | ])
26 |
27 | # ----- Stiffness matrix K and load vector f ---------------------
28 |
29 | K = np.matrix(np.zeros((12,12)))
30 | f = np.matrix(np.zeros((12,1)))
31 | f[3] = 2e+3
32 |
33 | # ----- Element stiffness and element load matrices -------------
34 |
35 | E = 200e9
36 | A1 = 2e-3
37 | A2 = 6e-3
38 | I1 = 1.6e-5
39 | I2 = 5.4e-5
40 |
41 | ep1 = np.array([E, A1, I1])
42 | ep3 = np.array([E, A2, I2])
43 | ex1 = np.array([0, 0])
44 | ex2 = np.array([6, 6])
45 | ex3 = np.array([0, 6])
46 | ey1 = np.array([4, 0])
47 | ey2 = np.array([4, 0])
48 | ey3 = np.array([4, 4])
49 | eq1 = np.array([0, 0])
50 | eq2 = np.array([0, 0])
51 | eq3 = np.array([0, -10e+3])
52 |
53 | Ke1 = cfc.beam2e(ex1, ey1, ep1)
54 | Ke2 = cfc.beam2e(ex2, ey2, ep1)
55 | Ke3, fe3 = cfc.beam2e(ex3, ey3, ep3, eq3)
56 |
57 | # ----- Assemble Ke into K ---------------------------------------
58 |
59 | cfc.assem(Edof[0,:], K, Ke1);
60 | cfc.assem(Edof[1,:], K, Ke2);
61 | cfc.assem(Edof[2,:], K, Ke3, f, fe3);
62 |
63 | # ----- Solve the system of equations and compute reactions ------
64 |
65 | bc = np.array([1,2,3,10,11])
66 | a, r = cfc.solveq(K,f,bc)
67 |
68 | print("a = ")
69 | print(a)
70 | print("r = ")
71 | print(r)
72 |
73 | # ----- Section forces -------------------------------------------
74 |
75 | Ed = cfc.extractEldisp(Edof,a);
76 |
77 | es1, ed1, ec1 = cfc.beam2s(ex1, ey1, ep1, Ed[0,:], eq1, nep=21)
78 | es2, ed2, ec2 = cfc.beam2s(ex2, ey2, ep1, Ed[1,:], eq2, nep=21)
79 | es3, ed3, ec3 = cfc.beam2s(ex3, ey3, ep3, Ed[2,:], eq3, nep=21)
80 |
81 | print("es1 = ")
82 | print(es1)
83 | print("es2 = ")
84 | print(es2)
85 | print("es3 = ")
86 | print(es3)
87 |
88 | # ----- Draw deformed frame ---------------------------------------
89 |
90 | ex = np.array([
91 | ex1, ex2, ex3
92 | ])
93 | print(ex)
94 |
95 | ey = np.array([
96 | ey1, ey2, ey3
97 | ])
98 | print(ey)
99 |
100 | plotpar = [2, 2, 1]
101 | cfv.eldraw2(ex, ey, plotpar=plotpar)
102 | cfv.showAndWait()
103 |
104 |
105 | #
106 | #cfv.eldraw2(ex, ey, plotpar=plotpar)
107 | ##cfv.eldisp2(ex, ey, Ed)
108 | #cfv.showAndWait()
109 |
110 | #figure(1)
111 | #plotpar=[2 1 0];
112 | #eldraw2(ex1,ey1,plotpar);
113 | #eldraw2(ex2,ey2,plotpar);
114 | #eldraw2(ex3,ey3,plotpar);
115 | #sfac=scalfact2(ex3,ey3,Ed(3,:),0.1);
116 | #plotpar=[1 2 1];
117 | #eldisp2(ex1,ey1,Ed(1,:),plotpar,sfac);
118 | #eldisp2(ex2,ey2,Ed(2,:),plotpar,sfac);
119 | #eldisp2(ex3,ey3,Ed(3,:),plotpar,sfac);
120 | #axis([-1.5 7.5 -0.5 5.5]);
121 | #pltscalb2(sfac,[1e-2 0.5 0]);
122 | #axis([-1.5 7.5 -0.5 5.5]);
123 | #title('displacements')
124 |
125 | #----- Draw normal force diagram --------------------------------
126 |
127 | #figure(2)
128 | #plotpar=[2 1];
129 | #sfac=scalfact2(ex1,ey1,es1(:,1),0.2);
130 | #eldia2(ex1,ey1,es1(:,1),plotpar,sfac);
131 | #eldia2(ex2,ey2,es2(:,1),plotpar,sfac);
132 | #eldia2(ex3,ey3,es3(:,1),plotpar,sfac);
133 | #axis([-1.5 7.5 -0.5 5.5]);
134 | #pltscalb2(sfac,[3e4 1.5 0]);
135 | #title('normal force')
136 |
137 | #----- Draw shear force diagram ---------------------------------
138 |
139 | #figure(3)
140 | #plotpar=[2 1];
141 | #sfac=scalfact2(ex3,ey3,es3(:,2),0.2);
142 | #eldia2(ex1,ey1,es1(:,2),plotpar,sfac);
143 | #eldia2(ex2,ey2,es2(:,2),plotpar,sfac);
144 | #eldia2(ex3,ey3,es3(:,2),plotpar,sfac);
145 | #axis([-1.5 7.5 -0.5 5.5]);
146 | #pltscalb2(sfac,[3e4 0.5 0]);
147 | #title('shear force')
148 |
149 | #----- Draw moment diagram --------------------------------------
150 |
151 | #figure(4)
152 | #plotpar=[2 1];
153 | #sfac=scalfact2(ex3,ey3,es3(:,3),0.2);
154 | #eldia2(ex1,ey1,es1(:,3),plotpar,sfac);
155 | #eldia2(ex2,ey2,es2(:,3),plotpar,sfac);
156 | #eldia2(ex3,ey3,es3(:,3),plotpar,sfac);
157 | #axis([-1.5 7.5 -0.5 5.5]);
158 | #pltscalb2(sfac,[3e4 0.5 0]);
159 | #title('moment')
160 |
161 |
--------------------------------------------------------------------------------
/examples/experimental/exui1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Mon Apr 11 09:44:29 2016
4 |
5 | @author: lindemann
6 | """
7 |
8 | import sys
9 |
10 | from qtpy.QtCore import Slot, Signal, QMetaObject
11 | from qtpy.QtWidgets import *
12 | from qtpy.QtGui import QPixmap
13 | from qtpy.uic import loadUi
14 |
15 | import calfem.vis_mpl as cfv
16 |
17 | class MainWindow(QMainWindow):
18 | """Main window class of our UI"""
19 | def __init__(self):
20 | """Constructor"""
21 | super(MainWindow, self).__init__()
22 |
23 | self.resize(640,480)
24 | self.move(50,50)
25 | self.setWindowTitle("MyWindow")
26 |
27 | self.executeButton = QPushButton("Tryck", self)
28 | self.executeButton.setObjectName("executeButton")
29 | self.executeButton.move(50,50)
30 | self.executeButton.resize(100,50)
31 |
32 | QMetaObject.connectSlotsByName(self)
33 |
34 | @Slot()
35 | def on_executeButton_clicked(self):
36 | print("Button pressed")
37 |
38 | def init_app():
39 | app = QApplication.instance()
40 |
41 | if app is None:
42 | print("No QApplication instance found. Creating one.")
43 | # if it does not exist then a QApplication is created
44 | app = QApplication(sys.argv)
45 | else:
46 | print("QApplication instance found.")
47 |
48 | return app
49 |
50 | def main_loop():
51 |
52 | app = QApplication.instance()
53 |
54 | if app is None:
55 | print("No QApplication instance found. Creating one.")
56 | # if it does not exist then a QApplication is created
57 | app = QApplication(sys.argv)
58 | else:
59 | print("QApplication instance found.")
60 |
61 | # För matplotlib kompatibilitet
62 |
63 | # plt.show(block=False)
64 |
65 | app.exec_()
66 |
67 |
68 | def show_window():
69 | app = init_app()
70 | widget = MainWindow()
71 | widget.show()
72 | app.exec_()
73 |
74 | if __name__ == '__main__':
75 |
76 | show_window()
77 | print("Hello")
78 | show_window()
79 | print("Hello after...")
--------------------------------------------------------------------------------
/examples/experimental/gmsh_api.py:
--------------------------------------------------------------------------------
1 | import gmsh
2 | import sys
3 |
4 | if __name__ == "__main__":
5 |
6 | gmsh.initialize(sys.argv)
7 | print(sys.argv)
8 | gmsh.finalize()
9 |
10 |
--------------------------------------------------------------------------------
/examples/experimental/gmsh_api2.py:
--------------------------------------------------------------------------------
1 | import gmsh
2 | import sys
3 | import numpy as np
4 | import calfem.mesh as cfm
5 | import calfem.vis_mpl as cfv
6 |
7 | if __name__ == "__main__":
8 |
9 | gmsh.initialize(sys.argv)
10 |
11 | gmsh.model.add("t1")
12 | gmsh.model.geo.add_point(0.0, 0.0, 0.0)
13 | gmsh.model.geo.add_point(1.0, 0.0, 0.0)
14 | gmsh.model.geo.add_point(1.0, 1.0, 0.0)
15 | gmsh.model.geo.add_point(0.0, 1.0, 0.0)
16 |
17 | gmsh.model.geo.add_line(1, 2)
18 | gmsh.model.geo.add_line(2, 3)
19 | gmsh.model.geo.add_line(3, 4)
20 | gmsh.model.geo.add_line(4, 1)
21 |
22 | gmsh.model.geo.add_curve_loop([1, 2, 3, 4], 1)
23 | gmsh.model.geo.add_plane_surface([1], 1)
24 |
25 | #gmsh.model.geo.add_surface_loop([1, 2, 3, 4])
26 |
27 | gmsh.model.geo.synchronize()
28 |
29 | #gmsh.option.setNumber("Mesh.ElementOrder", 5)
30 | # gmsh.option.setNumber("Mesh.HighOrderOptimize", 2)
31 | gmsh.option.setNumber("Mesh.RecombineAll", 1)
32 | #gmsh.option.setNumber('Mesh.MeshSizeMin', 0.025)
33 | #gmsh.option.setNumber('Mesh.MeshSizeMax', 0.025)
34 |
35 |
36 | gmsh.model.mesh.generate(2)
37 |
38 | print_entities()
39 |
40 | #gmsh.write("t1.msh")
41 |
42 | gmsh.fltk.run()
43 |
44 | gmsh.finalize()
45 |
46 |
--------------------------------------------------------------------------------
/examples/experimental/plot_tst.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | '''
4 | Example 02
5 | Creating geometry from B-Splines and circle arcs.
6 | Also shows how to set ID numbers for geometry entities and how to specify element density.
7 | '''
8 |
9 | import matplotlib.pyplot as plt
10 | import matplotlib.collections
11 | import numpy as np
12 |
13 | import calfem.geometry as cfg
14 | import calfem.mesh as cfm
15 | import calfem.vis_mpl as cfv
16 |
17 | # ---- Define geometry ------------------------------------------------------
18 |
19 | g = cfg.Geometry()
20 |
21 | # Add points:
22 | # In this example we set the IDs manually.
23 |
24 | g.point([ -2, 0], ID=0)
25 | g.point([ 0, 1], ID=1, elSize=5) # elSize determines the size of the elements near this point.
26 | g.point([ 1, 0], 2, elSize=5) # elSize is 1 by default. Larger number means less dense mesh.
27 | g.point([ 0, -2], 3) # Size means the length of the sides of the elements.
28 | g.point([ 0, 0], 4, elSize=5)
29 | g.point([ .5, .2], 5)
30 | g.point([-.5, .5], 6)
31 | g.point([-.7,-.5], 7)
32 |
33 | # Add curves:
34 |
35 | # The 3 points that define the circle arc are [start, center, end].
36 | # The arc must be smaller than Pi.
37 |
38 | g.circle([1, 4, 2], 2)
39 |
40 | # BSplines are similar to Splines, but do not necessarily pass through the
41 | # control points.
42 |
43 | g.bspline([5,6,7,5], 5)
44 | g.bspline([1,0,3,2], 4)
45 |
46 | # Add surface:
47 |
48 | g.surface([4,2], [[5]])
49 |
50 | # Markers do not have to be set when the curve is created. It can be done afterwards.
51 | # Set marker=80 for curves 2 and 4:
52 |
53 | for curveID in [2, 4]:
54 | g.curveMarker(curveID, 80)
55 |
56 | # ---- Generate mesh --------------------------------------------------------
57 |
58 | mesh = cfm.GmshMesh(g)
59 |
60 | # Element type 2 is triangle. (3 is quad. See user manual for more element types)
61 |
62 | mesh.el_type = 3
63 |
64 | # Degrees of freedom per node.
65 |
66 | mesh.dofs_per_node = 2
67 | mesh.el_size_factor = 0.05
68 | # mesh.gmsh_exec_path = "D:\\vsmn20-software\\gmsh\gmsh.exe"
69 |
70 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
71 |
72 | # ---- Visualise mesh -------------------------------------------------------
73 |
74 | # Hold left mouse button to pan.
75 | # Hold right mouse button to zoom.
76 |
77 | # Draw the geometry.
78 |
79 | #cfv.draw_geometry(g, labelCurves=True)
80 |
81 | # New figure window
82 |
83 | cfv.figure()
84 |
85 | # Draws the mesh.
86 |
87 | cfv.draw_mesh(
88 | coords=coords,
89 | edof=edof,
90 | dofs_per_node = mesh.dofs_per_node,
91 | el_type=mesh.el_type,
92 | filled=True,
93 | title="Example 02"
94 | )
95 |
96 | # Show grid
97 |
98 | #cfv.show_grid()
99 |
100 | # Enter main loop
101 |
102 | cfv.show_and_wait()
103 |
--------------------------------------------------------------------------------
/examples/experimental/point_in_geom.py:
--------------------------------------------------------------------------------
1 | import calfem.geometry as cfg
2 | import calfem.mesh as cfm
3 | import calfem.vis_mpl as cfv
4 | import calfem.utils as cfu
5 | import calfem.core as cfc
6 |
7 | import matplotlib.pyplot as plt
8 | import matplotlib as mpl
9 | import matplotlib.tri as tri
10 |
11 | import numpy as np
12 |
13 | # ---- Create Geometry ------------------------------------------------------
14 |
15 | g = cfg.geometry()
16 |
17 | # Add Points:
18 |
19 | points = [
20 | [0,0],
21 | [0,100],
22 | [0,150],
23 | [100,0],
24 | [150,0],
25 | [100,-100],
26 | [150,-100]
27 | ]
28 |
29 | for p in points:
30 | g.point(p)
31 |
32 | # Add Splines:
33 |
34 | g.spline([1,2], marker=2, elOnCurve=4)
35 | g.spline([3,4], elOnCurve=4)
36 | g.circle([1,0,3], elOnCurve = 10)
37 | g.circle([2,0,4], elOnCurve = 10)
38 | g.spline([3,5], elOnCurve = 6)
39 | g.spline([5,6], marker=3, elOnCurve = 4)
40 | g.spline([6,4], elOnCurve = 6)
41 |
42 | # Add Surfaces:
43 | #
44 | # When we set markers for surfaces, and have 2D elements, we can find which
45 | # region an element is in via the list 'elementmarkers', which is returned by
46 | # GmshMesher.create()
47 |
48 | g.structuredSurface([0,2,1,3], marker = 10)
49 | g.structuredSurface([1,4,5,6], marker = 11)
50 |
51 | el_type = 16
52 | dofs_per_node = 1
53 |
54 | mesh = cfm.GmshMeshGenerator(g, el_type, dofs_per_node)
55 | coords, edof, dofs, bdofs, elementmarkers = mesh.create()
56 |
57 |
58 | # ---- Visualise results ----------------------------------------------------
59 |
60 | print("Visualising...")
61 |
62 | mpl.rcParams['figure.dpi'] = 160
63 |
64 | cfv.figure()
65 |
66 | cfv.draw_geometry(g, title="Geometry")
67 |
68 | cfv.point_in_geometry(g, [0.0, 0.0])
69 |
70 | cfv.show_and_wait()
71 |
72 | print("Done.")
73 |
--------------------------------------------------------------------------------
/examples/experimental/qt1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed Mar 1 16:23:37 2017
4 |
5 | @author: Jonas Lindemann
6 | """
7 |
8 | import sys
9 | import time
10 |
11 | from calfem.qt5 import *
12 |
13 | import calfem.geometry as cfg
14 | import calfem.mesh as cfm
15 | import calfem.vis as cfv
16 |
17 | class MainWindow(QMainWindow):
18 | def __init__(self):
19 | """Constructor"""
20 | super(MainWindow, self).__init__()
21 |
22 | if __name__ == "__main__":
23 |
24 | app = QApplication(sys.argv)
25 | widget = MainWindow()
26 | widget.show()
27 | sys.exit(app.exec_())
28 |
--------------------------------------------------------------------------------
/examples/experimental/qt2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Fri Mar 9 17:14:04 2018
4 |
5 | @author: Jonas Lindemann
6 | """
7 |
8 | # -*- coding: utf-8 -*-
9 | """
10 | Created on Mon Apr 11 09:44:29 2016
11 |
12 | @author: lindemann
13 | """
14 |
15 | import sys
16 |
17 | from PyQt5.QtWidgets import *
18 |
19 | class MyWindow(QWidget):
20 | """Main Window class for our application"""
21 |
22 | def __init__(self):
23 | """Class constructor"""
24 | super().__init__()
25 |
26 | self.init_ui()
27 |
28 | def init_ui(self):
29 |
30 | self.resize(200,200)
31 | self.move(50,50)
32 | self.setWindowTitle("MyWindow")
33 |
34 | self.main_widget = QWidget(self)
35 |
36 | self.button1 = QPushButton('Button1')
37 | self.button2 = QPushButton('Button2')
38 | self.button3 = QPushButton('Button3')
39 | self.button4 = QPushButton('Button4')
40 |
41 | self.button5 = QPushButton('Button5')
42 | self.button6 = QPushButton('Button6')
43 | self.button7 = QPushButton('Button7')
44 | self.button8 = QPushButton('Button8')
45 |
46 | self.vbox = QVBoxLayout(self)
47 | self.vbox.addWidget(self.button1)
48 | self.vbox.addWidget(self.button2)
49 | self.vbox.addWidget(self.button3)
50 | self.vbox.addWidget(self.button4)
51 |
52 | self.hbox = QHBoxLayout(self)
53 | self.hbox.addWidget(self.button5)
54 | self.hbox.addWidget(self.button6)
55 | self.hbox.addWidget(self.button7)
56 | self.hbox.addWidget(self.button8)
57 |
58 | self.vbox.addLayout(self.hbox)
59 |
60 | self.main_widget.setLayout(self.vbox)
61 | self.setCentralWidget(self.main_widget)
62 |
63 |
64 | if __name__ == '__main__':
65 |
66 | app = QApplication(sys.argv)
67 |
68 | window = MyWindow()
69 | window.show()
70 |
71 | sys.exit(app.exec_())
72 |
--------------------------------------------------------------------------------
/examples/experimental/tri_mesh.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import matplotlib.pyplot as plt
4 | import matplotlib as mpl
5 | import matplotlib.tri as tri
6 |
7 | import calfem.geometry as cfg
8 | import calfem.mesh as cfm
9 | import calfem.vis_mpl as cfv
10 | import calfem.utils as cfu
11 | import calfem.core as cfc
12 |
13 | import numpy as np
14 |
15 | coords = np.array([
16 | [0.000, 0.000],
17 | [1.000, 0.000],
18 | [2.000, 0.500],
19 | [0.000, 1.000],
20 | [1.000, 1.000],
21 | [1.750, 1.300],
22 | [1.000, 1.700]])
23 |
24 | edof = np.array([
25 | [1, 2, 5],
26 | [5, 4, 1],
27 | [2, 3, 6],
28 | [6, 5, 2],
29 | [4, 5, 7],
30 | [5, 6, 7]])
31 |
32 | values = [1, 2, 1, 2, 7, 4, 5]
33 |
34 | plt.figure()
35 | cfv.draw_nodal_values_contours(values, coords, edof)
36 | plt.colorbar()
37 |
38 | plt.figure()
39 | cfv.draw_nodal_values_shaded(values, coords, edof)
40 | plt.colorbar()
41 |
42 | plt.show()
--------------------------------------------------------------------------------
/examples/exs_bar2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs3
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of a plane truss.
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # Ola Dahlblom 2004-09-07
11 | # Jonas Lindemann 2009-01-25
12 | # Ola Dahlblom 2023-02-02
13 | # ----------------------------------------------------------------
14 |
15 | import numpy as np
16 | import calfem.core as cfc
17 | import calfem.utils as cfu
18 | import calfem.vis_mpl as cfv
19 |
20 | cfu.disp_h1("Analysis of a plane truss.")
21 |
22 | # ----- Topology matrix Edof -------------------------------------
23 |
24 | edof = np.array([
25 | [1, 2, 5, 6],
26 | [5, 6, 7, 8],
27 | [3, 4, 5, 6]
28 | ])
29 |
30 | # ----- Stiffness matrix K and load vector f ---------------------
31 |
32 | K = np.array(np.zeros((8, 8)))
33 | f = np.array(np.zeros((8, 1)))
34 |
35 | # ----- Element properties ---------------------------------------
36 |
37 | E = 2.0e11
38 | A1 = 6.0e-4
39 | A2 = 3.0e-4
40 | A3 = 10.0e-4
41 | ep1 = [E, A1]
42 | ep2 = [E, A2]
43 | ep3 = [E, A3]
44 |
45 | # ----- Element coordinates --------------------------------------
46 |
47 | ex1 = np.array([0.0, 1.6])
48 | ex2 = np.array([1.6, 1.6])
49 | ex3 = np.array([0.0, 1.6])
50 |
51 | ey1 = np.array([0.0, 0.0])
52 | ey2 = np.array([0.0, 1.2])
53 | ey3 = np.array([1.2, 0.0])
54 |
55 | # ----- Element stiffness matrices ------------------------------
56 |
57 | Ke1 = cfc.bar2e(ex1, ey1, ep1)
58 | Ke2 = cfc.bar2e(ex2, ey2, ep2)
59 | Ke3 = cfc.bar2e(ex3, ey3, ep3)
60 |
61 | # ----- Assemble Ke into K ---------------------------------------
62 |
63 | K = cfc.assem(edof[0, :], K, Ke1)
64 | K = cfc.assem(edof[1, :], K, Ke2)
65 | K = cfc.assem(edof[2, :], K, Ke3)
66 |
67 | cfu.disp_h2("Stiffness matrix K:")
68 | cfu.disp_array(K)
69 |
70 | # ----- Solve the system of equations ----------------------------
71 |
72 | bc = np.array([1, 2, 3, 4, 7, 8])
73 | f[5] = -80e3
74 | a, r = cfc.solveq(K, f, bc)
75 |
76 | cfu.disp_h2("Displacements a:")
77 | cfu.disp_array(a)
78 |
79 | cfu.disp_h2("Reaction forces r:")
80 | cfu.disp_array(r)
81 |
82 | # ----- Element forces -------------------------------------------
83 |
84 | ed1 = cfc.extract_ed(edof[0, :], a)
85 | N1 = cfc.bar2s(ex1, ey1, ep1, ed1)
86 | ed2 = cfc.extract_ed(edof[1, :], a)
87 | N2 = cfc.bar2s(ex2, ey2, ep2, ed2)
88 | ed3 = cfc.extract_ed(edof[2, :], a)
89 | N3 = cfc.bar2s(ex3, ey3, ep3, ed3)
90 |
91 | cfu.disp_h2("Element forces r:")
92 |
93 | print("N1 = ")
94 | print(N1)
95 | print("N2 = ")
96 | print(N2)
97 | print("N3 = ")
98 | print(N3)
99 |
100 | # ----- Draw deformed frame ---------------------------------------
101 |
102 | plotpar = [2, 1, 0]
103 | sfac = cfv.scalfact2(ex3, ey3, ed1, 0.1)
104 | print("sfac=")
105 | print(sfac)
106 |
107 | cfv.figure(1)
108 | cfv.eldraw2(ex1, ey1, plotpar)
109 | cfv.eldraw2(ex2, ey2, plotpar)
110 | cfv.eldraw2(ex3, ey3, plotpar)
111 |
112 | plotpar = [1, 2, 1]
113 | cfv.eldisp2(ex1, ey1, ed1, plotpar, sfac)
114 | cfv.eldisp2(ex2, ey2, ed2, plotpar, sfac)
115 | cfv.eldisp2(ex3, ey3, ed3, plotpar, sfac)
116 | cfv.axis([-0.4, 2.0, -0.4, 1.4])
117 | plotpar1 = 2
118 | cfv.scalgraph2(sfac, [1e-3, 0, -0.3], plotpar1)
119 | cfv.title("Displacements")
120 |
121 | # ----- Draw normal force diagram --------------------------------
122 |
123 | plotpar = [2, 1]
124 | sfac = cfv.scalfact2(ex1, ey1, N2[:, 0], 0.1)
125 | cfv.figure(2)
126 | cfv.secforce2(ex1, ey1, N1[:, 0], plotpar, sfac)
127 | cfv.secforce2(ex2, ey2, N2[:, 0], plotpar, sfac)
128 | cfv.secforce2(ex3, ey3, N3[:, 0], plotpar, sfac)
129 | cfv.axis([-0.4, 2.0, -0.4, 1.4])
130 | cfv.scalgraph2(sfac, [5e4, 0, -0.3], plotpar1)
131 | cfv.title("Normal force")
132 |
133 | cfv.show_and_wait()
134 |
--------------------------------------------------------------------------------
/examples/exs_bar2_la.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs_bar2_la
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of a plane truss using loops.
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # P-E Austrell 1994-03-08
11 | # K-G Olsson 1995-09-28
12 | # O Dahlblom 2004-08-31
13 | # J Lindemann 2009-01-25
14 | # O Dahlblom 2023-02-02
15 | # ----------------------------------------------------------------
16 |
17 | import numpy as np
18 | import calfem.core as cfc
19 | import calfem.utils as cfu
20 |
21 | cfu.disp_h1("Analysis of a plane truss using loops")
22 |
23 | # ----- Topology matrix Edof -------------------------------------
24 |
25 | edof = np.array([
26 | [1, 2, 5, 6],
27 | [3, 4, 7, 8],
28 | [5, 6, 9, 10],
29 | [7, 8, 11, 12],
30 | [7, 8, 5, 6],
31 | [11, 12, 9, 10],
32 | [3, 4, 5, 6],
33 | [7, 8, 9, 10],
34 | [1, 2, 7, 8],
35 | [5, 6, 11, 12],
36 | ])
37 |
38 | # ----- Stiffness matrix K and load vector f ---------------------
39 |
40 | K = np.zeros([12, 12])
41 | f = np.zeros([12, 1])
42 | f[10] = 0.5e6 * np.sin(np.pi / 6)
43 | f[11] = -0.5e6 * np.cos(np.pi / 6)
44 |
45 | # ----- Element properties ---------------------------------------
46 |
47 | A = 25.0e-4
48 | E = 2.1e11
49 | ep = [E, A]
50 |
51 | # ----- Element coordinates --------------------------------------
52 |
53 | ex = np.array([
54 | [0.0, 2.0],
55 | [0.0, 2.0],
56 | [2.0, 4.0],
57 | [2.0, 4.0],
58 | [2.0, 2.0],
59 | [4.0, 4.0],
60 | [0.0, 2.0],
61 | [2.0, 4.0],
62 | [0.0, 2.0],
63 | [2.0, 4.0],
64 | ])
65 |
66 | ey = np.array([
67 | [2.0, 2.0],
68 | [0.0, 0.0],
69 | [2.0, 2.0],
70 | [0.0, 0.0],
71 | [0.0, 2.0],
72 | [0.0, 2.0],
73 | [0.0, 2.0],
74 | [0.0, 2.0],
75 | [2.0, 0.0],
76 | [2.0, 0.0],
77 | ])
78 |
79 | # ----- Create element stiffness matrices Ke and assemble into K -
80 |
81 | for elx, ely, eltopo in zip(ex, ey, edof):
82 | Ke = cfc.bar2e(elx, ely, ep)
83 | cfc.assem(eltopo, K, Ke)
84 |
85 | cfu.disp_h2("Stiffness matrix K:")
86 | cfu.disp_array(K)
87 |
88 | # ----- Solve the system of equations ----------------------------
89 |
90 | bc = np.array([1, 2, 3, 4])
91 | a, r = cfc.solveq(K, f, bc)
92 |
93 | cfu.disp_h2("Displacements a:")
94 | cfu.disp_array(a)
95 |
96 | cfu.disp_h2("Reaction forces r:")
97 | cfu.disp_array(r)
98 |
99 | # ----- Element forces -------------------------------------------
100 |
101 | ed = cfc.extract_ed(edof, a)
102 | N = np.zeros([edof.shape[0]])
103 |
104 | cfu.disp_h2("Element forces:")
105 |
106 | i = 0
107 | for elx, ely, eld in zip(ex, ey, ed):
108 | es = cfc.bar2s(elx, ely, ep, eld)
109 | N[i] = es[0][0]
110 | print("N%d = %g" % (i + 1, N[i]))
111 | i += 1
112 |
--------------------------------------------------------------------------------
/examples/exs_bar2_lb.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs_bar2_la
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of a plane truss using loops and extraction of
7 | # element coordinates from a global coordinate matrix.
8 | # ----------------------------------------------------------------
9 |
10 | # REFERENCES
11 | # P-E Austrell 1994-03-08
12 | # K-G Olsson 1995-09-28
13 | # O Dahlblom 2004-08-31
14 | # J Lindemann 2009-01-25
15 | # O Dahlblom 2019-12-16
16 | # O Dahlblom 2023-02-02
17 | # ----------------------------------------------------------------
18 |
19 | import numpy as np
20 | import calfem.core as cfc
21 | import calfem.utils as cfu
22 |
23 | cfu.disp_h1("Analysis of a plane truss using loops and extraction of element coordinates from a global coordinate matrix.")
24 |
25 | # ----- Topology matrix Edof -------------------------------------
26 |
27 | edof = np.array([
28 | [1, 2, 5, 6],
29 | [3, 4, 7, 8],
30 | [5, 6, 9, 10],
31 | [7, 8, 11, 12],
32 | [7, 8, 5, 6],
33 | [11, 12, 9, 10],
34 | [3, 4, 5, 6],
35 | [7, 8, 9, 10],
36 | [1, 2, 7, 8],
37 | [5, 6, 11, 12],
38 | ])
39 |
40 | # ----- Stiffness matrix K and load vector f ---------------------
41 |
42 | K = np.zeros([12, 12])
43 | f = np.zeros([12, 1])
44 | f[10] = 0.5e6 * np.sin(np.pi / 6)
45 | f[11] = -0.5e6 * np.cos(np.pi / 6)
46 |
47 | # ----- Element properties ---------------------------------------
48 |
49 | A = 25.0e-4
50 | E = 2.1e11
51 | ep = [E, A]
52 |
53 | # ----- Global coordinates and topology --------------------------
54 |
55 | coord = np.array([
56 | [0, 2],
57 | [0, 0],
58 | [2, 2],
59 | [2, 0],
60 | [4, 2],
61 | [4, 0]
62 | ])
63 |
64 | dof = np.array([
65 | [1, 2],
66 | [3, 4],
67 | [5, 6],
68 | [7, 8],
69 | [9, 10],
70 | [11, 12]
71 | ])
72 |
73 | # ----- Element coordinates --------------------------------------
74 |
75 | ex, ey = cfc.coordxtr(edof, coord, dof, 2)
76 |
77 | # ----- Create element stiffness matrices Ke and assemble into K -
78 |
79 | for elx, ely, eltopo in zip(ex, ey, edof):
80 | Ke = cfc.bar2e(elx, ely, ep)
81 | cfc.assem(eltopo, K, Ke)
82 |
83 | cfu.disp_h2("Stiffness matrix K:")
84 | cfu.disp_array(K)
85 |
86 | # ----- Solve the system of equations ----------------------------
87 |
88 | bc = np.array([1, 2, 3, 4])
89 | a, r = cfc.solveq(K, f, bc)
90 |
91 | cfu.disp_h2("Displacements a:")
92 | cfu.disp_array(a)
93 |
94 | cfu.disp_h2("Reaction forces r:")
95 | cfu.disp_array(r)
96 |
97 | # ----- Element forces -------------------------------------------
98 |
99 | ed = cfc.extract_ed(edof, a)
100 | N = np.zeros([edof.shape[0]])
101 |
102 | cfu.disp_h2("Element forces:")
103 |
104 | i = 0
105 | for elx, ely, eld in zip(ex, ey, ed):
106 | es = cfc.bar2s(elx, ely, ep, eld)
107 | N[i] = es[0][0]
108 | print("N%d = %g" % (i + 1, N[i]))
109 | i += 1
110 |
--------------------------------------------------------------------------------
/examples/exs_beam1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs_beam1
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of a simply supported beam.
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # Ola Dahlblom 2015-11-13
11 | # Ola Dahlblom 2019-12-11
12 | # Ola Dahlblom 2022-07-11
13 | # ----------------------------------------------------------------
14 |
15 | import numpy as np
16 | import matplotlib.pyplot as plt
17 | import calfem.core as cfc
18 | import calfem.utils as cfu
19 | import calfem.vis_mpl as cfv
20 |
21 | # ----- Topology -------------------------------------------------
22 |
23 | edof = np.array([
24 | [1, 2, 3, 4],
25 | [3, 4, 5, 6]
26 | ])
27 |
28 | # ----- Stiffness matrix K and load vector f ---------------------
29 |
30 | K = np.array(np.zeros((6, 6)))
31 | f = np.array(np.zeros((6, 1)))
32 | f[2] = -10e3
33 |
34 | # ----- Element stiffness and element load matrices -------------
35 |
36 | E = 210e9
37 | I = 2510e-8
38 |
39 | ep = np.array([E, I])
40 | ex1 = np.array([0, 3])
41 | ex2 = np.array([3, 9])
42 | eq1 = np.array([0])
43 | eq2 = np.array([0])
44 |
45 | Ke1 = cfc.beam1e(ex1, ep)
46 | Ke2 = cfc.beam1e(ex2, ep)
47 |
48 | # ----- Assemble Ke into K ---------------------------------------
49 |
50 | cfc.assem(edof[0, :], K, Ke1)
51 | cfc.assem(edof[1, :], K, Ke2)
52 |
53 | # ----- Solve the system of equations and compute reactions ------
54 |
55 | bc = np.array([1, 5])
56 | a, r = cfc.solveq(K, f, bc)
57 |
58 | cfu.disp_array(a, ["a"])
59 | cfu.disp_array(r, ["r"])
60 |
61 | # ----- Section forces -------------------------------------------
62 |
63 | ed = cfc.extract_ed(edof, a)
64 |
65 | es1, ed1, ec1 = cfc.beam1s(ex1, ep, ed[0, :], eq1, nep=4)
66 | es2, ed2, ec2 = cfc.beam1s(ex2, ep, ed[1, :], eq2, nep=7)
67 |
68 | cfu.disp_h2("es1")
69 | cfu.disp_array(es1, ["V1", "M1"])
70 | cfu.disp_h2("ed1")
71 | cfu.disp_array(ed1, ["v1"])
72 | cfu.disp_h2("ec1")
73 | cfu.disp_array(ec1, ["x1"])
74 | cfu.disp_h2("es2")
75 | cfu.disp_array(es2, ["V2", "M2"])
76 | cfu.disp_h2("ed2")
77 | cfu.disp_array(ed2, ["v2"])
78 | cfu.disp_h2("ec2")
79 | cfu.disp_array(ec2, ["x2"])
80 |
81 | # ----- Draw deformed beam ---------------------------------------
82 |
83 | cfv.figure(1)
84 | plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
85 | plt.plot(
86 | np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
87 | np.concatenate(([0], ed1[:, 0], ed2[:, 0], [0]), 0),
88 | color=(0.0, 0.0, 0.0),
89 | )
90 | cfv.title("displacements")
91 |
92 | # ----- Draw shear force diagram----------------------------------
93 |
94 | cfv.figure(2)
95 | plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
96 | plt.plot(
97 | np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
98 | -np.concatenate(([0], es1[:, 0], es2[:, 0], [0]), 0) / 1000,
99 | color=(0.0, 0.0, 0.0),
100 | )
101 | cfv.title("shear force")
102 |
103 | # ----- Draw moment diagram----------------------------------
104 |
105 | cfv.figure(3)
106 | plt.plot([0, 9], [0, 0], color=(0.8, 0.8, 0.8))
107 | plt.plot(
108 | np.concatenate(([0], ec1[:, 0], 3 + ec2[:, 0], [9]), 0),
109 | -np.concatenate(([0], es1[:, 1], es2[:, 1], [0]), 0) / 1000,
110 | color=(0.0, 0.0, 0.0),
111 | )
112 | cfv.title("bending moment")
113 |
114 | cfv.show_and_wait()
115 |
--------------------------------------------------------------------------------
/examples/exs_beambar2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs_beam2
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of a combined beam and bar structure.
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # Ola Dahlblom 2015-11-16
11 | # Ola Dahlblom 2019-12-19
12 | # Ola Dahlblom 2023-02-02
13 | # Copyright (c) Division of Structural Mechanics and
14 | # Division of Solid Mechanics.
15 | # Lund University
16 | # ----------------------------------------------------------------
17 |
18 | import numpy as np
19 | import calfem.core as cfc
20 | import calfem.utils as cfu
21 | import calfem.vis_mpl as cfv
22 |
23 | #np.set_printoptions(precision=3, suppress=True)
24 |
25 | # ----- Topology -------------------------------------------------
26 |
27 | edof1 = np.array([
28 | [1, 2, 3, 4, 5, 6],
29 | [4, 5, 6, 7, 8, 9],
30 | [7, 8, 9, 10, 11, 12]
31 | ])
32 |
33 | edof2 = np.array([
34 | [13, 14, 4, 5],
35 | [13, 14, 7, 8]
36 | ])
37 |
38 | # ----- Stiffness matrix K and load vector f ---------------------
39 |
40 | K = np.array(np.zeros((14, 14)))
41 | f = np.array(np.zeros((14, 1)))
42 |
43 | # ----- Element stiffness and element load matrices -------------
44 |
45 | E = 200.e9
46 | A1 = 4.e-3
47 | I1 = 5.4e-5
48 | A2 = 1.e-3
49 |
50 | ep1 = np.array([E, A1, I1])
51 | ep4 = np.array([E, A2])
52 |
53 | eq1 = np.array([0, 0])
54 | eq2 = np.array([0, -10e+3])
55 |
56 | ex1 = np.array([0, 2])
57 | ex2 = np.array([2, 4])
58 | ex3 = np.array([4, 6])
59 | ex4 = np.array([0, 2])
60 | ex5 = np.array([0, 4])
61 | ey1 = np.array([2, 2])
62 | ey2 = np.array([2, 2])
63 | ey3 = np.array([2, 2])
64 | ey4 = np.array([0, 2])
65 | ey5 = np.array([0, 2])
66 |
67 | Ke1 = cfc.beam2e(ex1, ey1, ep1)
68 | Ke2, fe2 = cfc.beam2e(ex2, ey2, ep1, eq2)
69 | Ke3, fe3 = cfc.beam2e(ex3, ey3, ep1, eq2)
70 | Ke4 = cfc.bar2e(ex4, ey4, ep4)
71 | Ke5 = cfc.bar2e(ex5, ey5, ep4)
72 |
73 | # ----- Assemble Ke into K ---------------------------------------
74 |
75 | K = cfc.assem(edof1[0, :], K, Ke1)
76 | K, f = cfc.assem(edof1[1, :], K, Ke2, f, fe2)
77 | K, f = cfc.assem(edof1[2, :], K, Ke3, f, fe3)
78 | K = cfc.assem(edof2[0, :], K, Ke4)
79 | K = cfc.assem(edof2[1, :], K, Ke5)
80 |
81 | # ----- Solve the system of equations and compute reactions ------
82 |
83 | bc = np.array([1, 2, 3, 13, 14])
84 | a, r = cfc.solveq(K, f, bc)
85 |
86 | cfu.disp_h2("Displacements a:")
87 | cfu.disp_array(a)
88 |
89 | cfu.disp_h2("Reaction forces r:")
90 | cfu.disp_array(r)
91 |
92 | # ----- Section forces -------------------------------------------
93 |
94 | ed1 = cfc.extract_ed(edof1, a)
95 | ed2 = cfc.extract_ed(edof2, a)
96 |
97 | es1, _, _ = cfc.beam2s(ex1, ey1, ep1, ed1[0, :], eq1, nep=11)
98 | es2, _, _ = cfc.beam2s(ex2, ey2, ep1, ed1[1, :], eq2, nep=11)
99 | es3, _, _ = cfc.beam2s(ex3, ey3, ep1, ed1[2, :], eq2, nep=11)
100 | es4 = cfc.bar2s(ex4, ey4, ep4, ed2[0, :])
101 | es5 = cfc.bar2s(ex5, ey5, ep4, ed2[1, :])
102 |
103 | cfu.disp_h2("es1 = ")
104 | cfu.disp_array(es1, headers=["N", "Q", "M"])
105 | cfu.disp_h2("es2 = ")
106 | cfu.disp_array(es2, headers=["N", "Q", "M"])
107 | cfu.disp_h2("es3 = ")
108 | cfu.disp_array(es3, headers=["N", "Q", "M"])
109 | cfu.disp_h2("es4 = ")
110 | cfu.disp_array(es4, headers=["N"])
111 | cfu.disp_h2("es5 = ")
112 | cfu.disp_array(es5, headers=["N"])
113 |
114 |
--------------------------------------------------------------------------------
/examples/exs_flw_diff2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # example exs8
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of two dimensional diffusion
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # Karl-Gunnar Olsson 1995-10-08
11 | # Ola Dahlblom 2004-09-14
12 | # ----------------------------------------------------------------
13 |
14 | import numpy as np
15 | import calfem.vis_mpl as cfv
16 | import calfem.core as cfc
17 | import calfem.utils as cfu
18 |
19 | # ----- System matrices -----
20 |
21 | K = np.zeros((15, 15))
22 | f = np.zeros((15, 1))
23 | Coord = np.array(
24 | [
25 | [0, 0],
26 | [0.025, 0],
27 | [0.05, 0],
28 | [0, 0.025],
29 | [0.025, 0.025],
30 | [0.05, 0.025],
31 | [0, 0.05],
32 | [0.025, 0.05],
33 | [0.05, 0.05],
34 | [0, 0.075],
35 | [0.025, 0.075],
36 | [0.05, 0.075],
37 | [0, 0.1],
38 | [0.025, 0.1],
39 | [0.05, 0.1],
40 | ]
41 | )
42 |
43 | Dof = np.array(
44 | [[1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12], [13], [14], [15]]
45 | )
46 |
47 | # ----- Element properties, topology and coordinates -----
48 |
49 | ep = np.array([1])
50 | D = np.array([[1, 0], [0, 1]])
51 | Edof = np.array(
52 | [
53 | [1, 2, 5, 4],
54 | [2, 3, 6, 5],
55 | [4, 5, 8, 7],
56 | [5, 6, 9, 8],
57 | [7, 8, 11, 10],
58 | [8, 9, 12, 11],
59 | [10, 11, 14, 13],
60 | [11, 12, 15, 14],
61 | ]
62 | )
63 | Ex, Ey = cfc.coordxtr(Edof, Coord, Dof)
64 |
65 | # ----- Generate FE-mesh -----
66 |
67 | # clf; eldraw2(Ex,Ey,[1 3 0],Edof(:,1));
68 | # disp('PRESS ENTER TO CONTINUE'); pause; clf;
69 |
70 | # ----- Create and assemble element matrices -----
71 |
72 | for i in range(8):
73 | Ke = cfc.flw2qe(Ex[i], Ey[i], ep, D)
74 | K = cfc.assem(Edof[i], K, Ke)
75 |
76 | # ----- Solve equation system -----
77 |
78 | bcPrescr = np.array([1, 2, 3, 4, 7, 10, 13, 14, 15])
79 | bcVal = np.array([0, 0, 0, 0, 0, 0, 0.5e-3, 1e-3, 1e-3])
80 | a, r = cfc.solveq(K, f, bcPrescr, bcVal)
81 |
82 | # ----- Compute element flux vector -----
83 |
84 | Ed = cfc.extractEldisp(Edof, a)
85 | Es = np.zeros((8, 2))
86 | for i in range(8):
87 | Es[i], Et = cfc.flw2qs(Ex[i], Ey[i], ep, D, Ed[i])
88 |
89 |
90 | # ----- Draw flux vectors and contourlines -----
91 |
92 | cfu.disp_h2("Ex")
93 | cfu.disp_array(Ex, headers=["x0", "x1", "x2", "x3"])
94 | cfu.disp_h2("Ey")
95 | cfu.disp_array(Ey, headers=["x0", "x1", "x2", "x3"])
96 | cfu.disp_h2("a")
97 | cfu.disp_array(a)
98 | cfu.disp_h2("Ed")
99 | cfu.disp_array(Ed, headers=["ed0", "ed1", "ed2", "ed3"])
100 |
101 | cfv.eldraw2(Ex, Ey, [1, 2, 1], range(1, Ex.shape[0] + 1))
102 | cfv.eliso2_mpl(Ex, Ey, Ed)
103 | cfv.show_and_wait()
104 |
--------------------------------------------------------------------------------
/examples/exs_flw_temp1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs_flw_temp1
4 | #----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of one dimensional heat flow.
7 | #----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # P-E Austrell 1994-03-08
11 | # K-G Olsson 1995-09-28
12 | # O Dahlblom 2004-09-07
13 | # O Dahlblom 2023-02-02
14 | # ----------------------------------------------------------------
15 |
16 | import numpy as np
17 | import calfem.core as cfc
18 | import calfem.utils as cfu
19 |
20 | # ----- Topology -------------------------------------------------
21 |
22 | edof = np.array([
23 | [1, 2],
24 | [2, 3],
25 | [3, 4],
26 | [4, 5],
27 | [5, 6]
28 | ])
29 |
30 | # ----- Stiffness matrix K and load vector f ---------------------
31 |
32 | K = np.array(np.zeros((6, 6)))
33 | f = np.array(np.zeros((6, 1)))
34 | f[3] = 10
35 |
36 | # ----- Element stiffness and element load matrices -------------
37 |
38 | ep1 = 25
39 | ep2 = 24.3
40 | ep3 = 0.4
41 | ep4 = 17
42 | ep5 = 7.7
43 |
44 | Ke1 = cfc.spring1e(ep1)
45 | Ke2 = cfc.spring1e(ep2)
46 | Ke3 = cfc.spring1e(ep3)
47 | Ke4 = cfc.spring1e(ep4)
48 | Ke5 = cfc.spring1e(ep5)
49 |
50 | # ----- Assemble Ke into K ---------------------------------------
51 |
52 | cfc.assem(edof[0, :], K, Ke1)
53 | cfc.assem(edof[1, :], K, Ke2)
54 | cfc.assem(edof[2, :], K, Ke3)
55 | cfc.assem(edof[3, :], K, Ke4)
56 | cfc.assem(edof[4, :], K, Ke5)
57 |
58 | # ----- Solve the system of equations ----------------------------
59 |
60 | bc = np.array([1, 6])
61 | bcVal = np.array([-17, 20])
62 | a, r = cfc.solveq(K, f, bc, bcVal)
63 |
64 | cfu.disp_h2("Temperatures a:")
65 | cfu.disp_array(a)
66 |
67 | cfu.disp_h2("Reaction flows r:")
68 | cfu.disp_array(r)
69 |
70 | # ----- Section forces -------------------------------------------
71 |
72 | ed1 = cfc.extract_ed(edof[0, :], a)
73 | ed2 = cfc.extract_ed(edof[1, :], a)
74 | ed3 = cfc.extract_ed(edof[2, :], a)
75 | ed4 = cfc.extract_ed(edof[3, :], a)
76 | ed5 = cfc.extract_ed(edof[4, :], a)
77 |
78 | q1 = cfc.spring1s(ep1, ed1)
79 | q2 = cfc.spring1s(ep2, ed2)
80 | q3 = cfc.spring1s(ep3, ed3)
81 | q4 = cfc.spring1s(ep4, ed4)
82 | q5 = cfc.spring1s(ep5, ed5)
83 |
84 | cfu.disp_h2("Element flows:")
85 |
86 | print("q1 = ")
87 | print(q1)
88 | print("q2 = ")
89 | print(q2)
90 | print("q3 = ")
91 | print(q3)
92 | print("q4 = ")
93 | print(q4)
94 | print("q5 = ")
95 | print(q5)
96 |
97 |
--------------------------------------------------------------------------------
/examples/exs_flw_temp2.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs2
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Analysis of one dimensional heat flow.
7 | # ----------------------------------------------------------------
8 |
9 | # REFERENCES
10 | # P-E Austrell 1994-03-08
11 | # K-G Olsson 1995-09-28
12 | # O Dahlblom 2004-09-07
13 | # J Lindemann 2009-01-25
14 | # ----------------------------------------------------------------
15 |
16 | import numpy as np
17 | import calfem.core as cfc
18 | import calfem.utils as cfu
19 |
20 | # ----- Topology matrix Edof -------------------------------------
21 |
22 | edof = np.array([
23 | [1, 2],
24 | [2, 3],
25 | [3, 4],
26 | [4, 5],
27 | [5, 6]
28 | ])
29 |
30 | # ----- Stiffness matrix K and load vector f ---------------------
31 |
32 | K = np.matrix(np.zeros((6, 6)))
33 | f = np.matrix(np.zeros((6, 1)))
34 | f[3] = 10.0
35 |
36 | # ----- Element properties ---------------------------------------
37 |
38 | ep1 = 25.0
39 | ep2 = 24.3
40 | ep3 = 0.4
41 | ep4 = 17.0
42 | ep5 = 7.7
43 |
44 | # ----- Element stiffness matrices ------------------------------
45 |
46 | Ke1 = cfc.spring1e(ep1)
47 | Ke2 = cfc.spring1e(ep2)
48 | Ke3 = cfc.spring1e(ep3)
49 | Ke4 = cfc.spring1e(ep4)
50 | Ke5 = cfc.spring1e(ep5)
51 |
52 | # ---- Assemble Ke into K ---------------------------------------
53 |
54 | cfc.assem(edof[0, :], K, Ke1)
55 | cfc.assem(edof[1, :], K, Ke2)
56 | cfc.assem(edof[2, :], K, Ke3)
57 | cfc.assem(edof[3, :], K, Ke4)
58 | cfc.assem(edof[4, :], K, Ke5)
59 |
60 | cfu.disp_h2("Stiffness matrix K:")
61 | cfu.disp_array(K)
62 |
63 | # ----- Solve the system of equations ----------------------------
64 |
65 | bc = np.array([1, 6])
66 | bcVal = np.array([-17.0, 20.0])
67 | a, r = cfc.solveq(K, f, bc, bcVal)
68 |
69 | cfu.disp_h2("Temperatures a:")
70 | cfu.disp_array(a)
71 |
72 | cfu.disp_h2("Reaction flows r:")
73 | cfu.disp_array(r)
74 |
75 | # ----- Element flows -------------------------------------------
76 |
77 | ed1 = cfc.extract_ed(edof[0, :], a)
78 | ed2 = cfc.extract_ed(edof[1, :], a)
79 | ed3 = cfc.extract_ed(edof[2, :], a)
80 | ed4 = cfc.extract_ed(edof[3, :], a)
81 | ed5 = cfc.extract_ed(edof[4, :], a)
82 |
83 | q1 = cfc.spring1s(ep1, ed1)
84 | q2 = cfc.spring1s(ep2, ed2)
85 | q3 = cfc.spring1s(ep3, ed3)
86 | q4 = cfc.spring1s(ep4, ed4)
87 | q5 = cfc.spring1s(ep5, ed5)
88 |
89 | cfu.disp_h2("Element flows r:")
90 |
91 | print("q1 = "+str(q1))
92 | print("q2 = "+str(q2))
93 | print("q3 = "+str(q3))
94 | print("q4 = "+str(q4))
95 | print("q5 = "+str(q5))
96 |
--------------------------------------------------------------------------------
/examples/exs_spring.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | #
3 | # example exs1
4 | # ----------------------------------------------------------------
5 | # PURPOSE
6 | # Linear elastic spring analysis. Introduction to the basic
7 | # steps in the finite element method.
8 | # ----------------------------------------------------------------
9 |
10 | # REFERENCES
11 | # P-E Austrell 1994-03-08
12 | # K-G Olsson 1995-09-28
13 | # O Dahlblom 2004-09-06
14 | # J Lindemann 2009-01-25
15 | # ----------------------------------------------------------------
16 |
17 | # ----- import necesarry mooules
18 |
19 | import numpy as np
20 | import calfem.core as cfc
21 | import calfem.utils as cfu
22 |
23 | # ----- Topology matrix Edof
24 |
25 | edof = np.array([
26 | [1, 2], # element 1 between node 1 and 2
27 | [2, 3], # element 2 between node 2 and 3
28 | [2, 3] # element 3 between node 2 and 3
29 | ])
30 |
31 | # ----- Stiffness matrix K and load vector f
32 |
33 | K = np.zeros((3, 3))
34 | f = np.zeros((3, 1))
35 |
36 | # ----- Element stiffness matrices
37 |
38 | k = 1500.
39 | ep1 = k
40 | ep2 = 2.*k
41 | Ke1 = cfc.spring1e(ep1)
42 | Ke2 = cfc.spring1e(ep2)
43 |
44 | # ----- Assemble Ke into K
45 |
46 | cfc.assem(edof[0, :], K, Ke2)
47 | cfc.assem(edof[1, :], K, Ke1)
48 | cfc.assem(edof[2, :], K, Ke2)
49 |
50 | cfu.disp_h2("Stiffness matrix K:")
51 | cfu.disp_array(K)
52 |
53 | # f[1] corresponds to edof 2
54 |
55 | f[1] = 100.0
56 |
57 | # ----- Solve the system of equations
58 |
59 | bc = np.array([1, 3])
60 | a, r = cfc.solveq(K, f, bc)
61 |
62 | cfu.disp_h2("Displacements a:")
63 | cfu.disp_array(a)
64 |
65 | cfu.disp_h2("Reaction forces r:")
66 | cfu.disp_array(r)
67 |
68 | # ----- Caculate element forces
69 |
70 | ed1 = cfc.extract_ed(edof[0, :], a)
71 | ed2 = cfc.extract_ed(edof[1, :], a)
72 | ed3 = cfc.extract_ed(edof[2, :], a)
73 |
74 | es1 = cfc.spring1s(ep2, ed1)
75 | es2 = cfc.spring1s(ep1, ed2)
76 | es3 = cfc.spring1s(ep2, ed3)
77 |
78 | cfu.disp_h2("Element forces N:")
79 | print("N1 = "+str(es1))
80 | print("N2 = "+str(es2))
81 | print("N3 = "+str(es3))
82 |
--------------------------------------------------------------------------------
/examples/exv1.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Example using Vedo, spring elements
4 |
5 | @author: Andreas Åmand
6 | """
7 |
8 | import numpy as np
9 | import calfem.core as cfc
10 | import calfem.vis_vedo as cfv
11 |
12 | coord = np.array([
13 | [0],
14 | [0.5],
15 | [1],
16 | [1.5]
17 | ])
18 |
19 | dof = np.array([
20 | [1],
21 | [2],
22 | [3],
23 | [4]
24 | ])
25 |
26 | edof = np.array([
27 | [1, 2],
28 | [2, 3],
29 | [3, 4]
30 | ])
31 |
32 | k = 1000
33 | ep = [3*k, k, 8*k]
34 |
35 | ndof = dof.shape[0]*dof.shape[1]
36 | nel = edof.shape[0]
37 | K = np.zeros([ndof,ndof])
38 | for i in range(nel):
39 | Ke = cfc.spring1e(ep[i])
40 | K = cfc.assem(edof[i],K,Ke)
41 |
42 | f = np.zeros([ndof,1])
43 | f[3,0] = 500 #Newton
44 |
45 | bcPrescr = np.array([1])
46 | a,r = cfc.solveq(K, f, bcPrescr)
47 |
48 | cfv.figure(1,flat=True)
49 | cfv.draw_mesh(edof,coord,dof,1)
50 | mesh = cfv.draw_displaced_mesh(edof,coord,dof,1,a,offset=[0,0.2,0],render_nodes=True)
51 | cfv.add_text_3D('k=3 kN/m',[0.15,-0.1,0],size=0.03)
52 | cfv.add_text_3D('k=1 kN/m',[0.65,-0.1,0],size=0.03)
53 | cfv.add_text_3D('k=8 kN/m',[1.15,-0.1,0],size=0.03)
54 | cfv.add_text_3D('F_x =500 N',[1.55,-0.02,0],size=0.03)
55 |
56 | # For exporting mesh
57 | cfv.export_vtk('export/exv1/exv1', mesh)
58 |
59 | cfv.figure(2)
60 | steps = 20
61 | cfv.add_text(f'Looping bewteen undef. & def. state w/ {steps} steps',pos='top-middle')
62 | cfv.animation(edof,coord,dof,1,a,loop=True,steps=20,dt=0,export=True,file='export/exv1/anim/exv1')
63 |
64 | #Start Calfem-vedo visualization
65 | cfv.show_and_wait()
66 |
67 | # For not exporting animation
68 | #cfv.animation(edof,coord,dof,1,a,loop=True,steps=20,dt=0)
69 |
70 |
--------------------------------------------------------------------------------
/examples/exv4.mat:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/examples/exv4.mat
--------------------------------------------------------------------------------
/examples/gmsh-api/exgm1.py:
--------------------------------------------------------------------------------
1 | import gmsh
2 | import sys
3 |
4 | lc = 0
5 |
6 | gmsh.initialize()
7 | gmsh.model.occ.addBox(0, 0, 0, 1, 1, 1, 1)
8 | gmsh.model.occ.synchronize()
9 |
10 | #gmsh.model.add_physical_group(1, [1, 2, 4], 5)
11 | #ps = gmsh.model.add_physical_group(2, [1])
12 | #gmsh.model.set_physical_name(2, ps, "My surface")
13 |
14 | #gmsh.option.setNumber("Mesh.MeshSizeFactor", 0.2)
15 | #gmsh.option.setNumber("Mesh.Algorithm", 6) # Frontal-Delaunay for 2D meshes
16 | #gmsh.option.setNumber("Mesh.Algorithm", 8) # Frontal-Delaunay for quads
17 | #gmsh.model.mesh.setAlgorithm(2, 33, 1)
18 | #gmsh.option.setNumber("Mesh.Smoothing", 100)
19 | #gmsh.option.setNumber("Mesh.RecombineAll", 1)
20 | #gmsh.option.setNumber("Mesh.RecombinationAlgorithm", 2) # or 3
21 |
22 | gmsh.model.mesh.generate(3)
23 |
24 | entities = gmsh.model.get_entities()
25 |
26 | tag = 1
27 | dim = 3
28 |
29 | node_tags, node_coords, node_params = gmsh.model.mesh.get_nodes(dim, tag)
30 | elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.get_elements(dim, tag)
31 | type = gmsh.model.get_type(dim, tag)
32 | name = gmsh.model.getEntityName(dim, tag)
33 |
34 | print("type =", type)
35 | print("tag =", tag)
36 |
37 | print("node_tags:", len(node_tags))
38 | print(node_tags)
39 | print("node_coords:", int(node_coords.shape[0]/3))
40 | print(node_coords.reshape((int(node_coords.shape[0]/3), 3)))
41 | print("node_params:", len(node_params))
42 | print(node_params)
43 | print("elem_types:", len(elem_types))
44 | print(elem_types)
45 | print("elem_tags:", len(elem_tags))
46 | print(elem_tags[0])
47 | print("elem_node_tags:", len(elem_node_tags))
48 | print(elem_node_tags[0])
49 |
50 | # for e in entities:
51 | # dim = e[0]
52 | # tag = e[1]
53 | # print(dim, tag)
54 | # node_tags, node_coords, node_params = gmsh.model.mesh.get_nodes(dim, tag)
55 | # elem_types, elem_tags, elem_node_tags = gmsh.model.mesh.get_elements(dim, tag)
56 |
57 | # type = gmsh.model.getType(e[0], e[1])
58 | # name = gmsh.model.getEntityName(e[0], e[1])
59 | # #if len(name): name += ' '
60 | # #print("Entity " + name + str(e) + " of type " + type)
61 |
62 | # num_elem = sum(len(i) for i in elem_tags)
63 | # #print(" - Mesh has " + str(len(node_tags)) + " nodes and " + str(num_elem) +
64 | # # " elements")
65 |
66 | # for i in elem_node_tags:
67 | # print(i)
68 |
69 |
70 |
71 | # # * Upward and downward adjacencies:
72 | # up, down = gmsh.model.get_adjacencies(e[0], e[1])
73 | # if len(up):
74 | # print(" - Upward adjacencies: " + str(up))
75 | # if len(down):
76 | # print(" - Downward adjacencies: " + str(down))
77 |
78 | # physicalTags = gmsh.model.getPhysicalGroupsForEntity(dim, tag)
79 | # if len(physicalTags):
80 | # s = ''
81 | # for p in physicalTags:
82 | # n = gmsh.model.getPhysicalName(dim, p)
83 | # if n: n += ' '
84 | # s += n + '(' + str(dim) + ', ' + str(p) + ') '
85 | # print(" - Physical groups: " + s)
86 |
87 | # partitions = gmsh.model.getPartitions(e[0], e[1])
88 | # if len(partitions):
89 | # print(" - Partition tags: " + str(partitions) + " - parent entity " +
90 | # str(gmsh.model.getParent(e[0], e[1])))
91 |
92 | # # * List all types of elements making up the mesh of the entity:
93 | # for t in elem_types:
94 | # name, dim, order, numv, parv, _ = gmsh.model.mesh.getElementProperties(t)
95 | # print(" - Element type: " + name + ", order " + str(order) + " (" +
96 | # str(numv) + " nodes in param coord: " + str(parv) + ")")
97 |
98 | gmsh.write("exgmsh1.msh")
99 |
100 | #if '-nopopup' not in sys.argv:
101 | #gmsh.fltk.run()
102 |
103 | gmsh.finalize()
--------------------------------------------------------------------------------
/examples/gmsh-api/exgm2.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------------------------
2 | #
3 | # Gmsh Python tutorial 16
4 | #
5 | # Constructive Solid Geometry, OpenCASCADE geometry kernel
6 | #
7 | # ------------------------------------------------------------------------------
8 |
9 | # Instead of constructing a model in a bottom-up fashion with Gmsh's built-in
10 | # geometry kernel, starting with version 3 Gmsh allows you to directly use
11 | # alternative geometry kernels. Here we will use the OpenCASCADE kernel.
12 |
13 | import gmsh
14 | import math
15 | import sys
16 |
17 | gmsh.initialize()
18 |
19 | gmsh.model.add("t16")
20 |
21 | # Let's build the same model as in `t5.py', but using constructive solid
22 | # geometry.
23 |
24 | # We can log all messages for further processing with:
25 | gmsh.logger.start()
26 |
27 | # We first create two cubes:
28 | gmsh.model.occ.addBox(0, 0, 0, 1, 1, 1, 1)
29 | gmsh.model.occ.addBox(0, 0, 0, 0.5, 0.5, 0.5, 2)
30 |
31 | # We apply a boolean difference to create the "cube minus one eigth" shape:
32 | gmsh.model.occ.cut([(3, 1)], [(3, 2)], 3)
33 |
34 | # Boolean operations with OpenCASCADE always create new entities. By default the
35 | # extra arguments `removeObject' and `removeTool' in `cut()' are set to `True',
36 | # which will delete the original entities.
37 |
38 | # We then create the five spheres:
39 | x = 0
40 | y = 0.75
41 | z = 0
42 | r = 0.09
43 | holes = []
44 |
45 | # If we had wanted five empty holes we would have used `cut()' again. Here we
46 | # want five spherical inclusions, whose mesh should be conformal with the mesh
47 | # of the cube: we thus use `fragment()', which intersects all volumes in a
48 | # conformal manner (without creating duplicate interfaces):
49 |
50 | # ov, ovv = gmsh.model.occ.fragment([(3, 3)], holes)
51 |
52 | # ov contains all the generated entities of the same dimension as the input
53 | # entities:
54 | #print("fragment produced volumes:")
55 | #for e in ov:
56 | # print(e)
57 |
58 | # ovv contains the parent-child relationships for all the input entities:
59 | #print("before/after fragment relations:")
60 | #for e in zip([(3, 3)] + holes, ovv):
61 | # print("parent " + str(e[0]) + " -> child " + str(e[1]))
62 |
63 | gmsh.model.occ.synchronize()
64 |
65 | # When the boolean operation leads to simple modifications of entities, and if
66 | # one deletes the original entities, Gmsh tries to assign the same tag to the
67 | # new entities. (This behavior is governed by the
68 | # `Geometry.OCCBooleanPreserveNumbering' option.)
69 |
70 | # Here the `Physical Volume' definitions can thus be made for the 5 spheres
71 | # directly, as the five spheres (volumes 4, 5, 6, 7 and 8), which will be
72 | # deleted by the fragment operations, will be recreated identically (albeit with
73 | # new surfaces) with the same tags:
74 | #for i in range(1, 6):
75 | # gmsh.model.addPhysicalGroup(3, [3 + i], i)
76 |
77 | # The tag of the cube will change though, so we need to access it
78 | # programmatically:
79 | #gmsh.model.addPhysicalGroup(3, [ov[-1][1]], 10)
80 |
81 | # Creating entities using constructive solid geometry is very powerful, but can
82 | # lead to practical issues for e.g. setting mesh sizes at points, or identifying
83 | # boundaries.
84 |
85 | # To identify points or other bounding entities you can take advantage of the
86 | # `getEntities()', `getBoundary()' and `getEntitiesInBoundingBox()' functions:
87 |
88 | lcar1 = .1
89 | lcar2 = .0005
90 | lcar3 = .055
91 |
92 | # Assign a mesh size to all the points:
93 | gmsh.model.mesh.setSize(gmsh.model.getEntities(0), lcar1)
94 |
95 | # Override this constraint on the points of the five spheres:
96 | #gmsh.model.mesh.setSize(gmsh.model.getBoundary(holes, False, False, True),
97 | # lcar3)
98 |
99 | # Select the corner point by searching for it geometrically:
100 | eps = 1e-3
101 | #ov = gmsh.model.getEntitiesInBoundingBox(0.5 - eps, 0.5 - eps, 0.5 - eps,
102 | # 0.5 + eps, 0.5 + eps, 0.5 + eps, 0)
103 | #gmsh.model.mesh.setSize(ov, lcar2)
104 |
105 | gmsh.model.mesh.generate(3)
106 |
107 | gmsh.write("t16.msh")
108 |
109 | # Additional examples created with the OpenCASCADE geometry kernel are available
110 | # in `t18.py', `t19.py' and `t20.py', as well as in the `demos/api' directory.
111 |
112 | # Inspect the log:
113 | log = gmsh.logger.get()
114 | print("Logger has recorded " + str(len(log)) + " lines")
115 | gmsh.logger.stop()
116 |
117 | # Launch the GUI to see the results:
118 | if '-nopopup' not in sys.argv:
119 | gmsh.fltk.run()
120 |
121 | gmsh.finalize()
122 |
--------------------------------------------------------------------------------
/examples/gmsh-api/exgm3.py:
--------------------------------------------------------------------------------
1 | # ------------------------------------------------------------------------------
2 | #
3 | # Gmsh Python tutorial 17
4 | #
5 | # Anisotropic background mesh
6 | #
7 | # ------------------------------------------------------------------------------
8 |
9 | # As seen in `t7.py', mesh sizes can be specified very accurately by providing a
10 | # background mesh, i.e., a post-processing view that contains the target mesh
11 | # sizes.
12 |
13 | # Here, the background mesh is represented as a metric tensor field defined on a
14 | # square. One should use bamg as 2d mesh generator to enable anisotropic meshes
15 | # in 2D.
16 |
17 | import gmsh
18 | import math
19 | import os
20 | import sys
21 |
22 | gmsh.initialize()
23 |
24 | gmsh.model.add("t17")
25 |
26 | # Create a square
27 | gmsh.model.occ.addRectangle(-1, -1, 0, 2, 2)
28 | gmsh.model.occ.synchronize()
29 |
30 | # Merge a post-processing view containing the target anisotropic mesh sizes
31 | path = os.path.dirname(os.path.abspath(__file__))
32 | gmsh.merge(os.path.join(path, os.pardir, 't17_bgmesh.pos'))
33 |
34 | # Apply the view as the current background mesh
35 | bg_field = gmsh.model.mesh.field.add("PostView")
36 | gmsh.model.mesh.field.setNumber(bg_field, "ViewIndex", 0)
37 | gmsh.model.mesh.field.setAsBackgroundMesh(bg_field)
38 |
39 | # Use bamg
40 | gmsh.option.setNumber("Mesh.SmoothRatio", 3)
41 | gmsh.option.setNumber("Mesh.AnisoMax", 1000)
42 | gmsh.option.setNumber("Mesh.Algorithm", 7)
43 |
44 | gmsh.model.mesh.generate(2)
45 | gmsh.write("t17.msh")
46 |
47 | # Launch the GUI to see the results:
48 | if '-nopopup' not in sys.argv:
49 | gmsh.fltk.run()
50 |
51 | gmsh.finalize()
52 |
--------------------------------------------------------------------------------
/examples/obsolete/extri1.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python
2 |
3 | import numpy as np
4 | import calfem.core as cfc
5 | import calfem.utils as cfu
6 | import calfem.vis as cfv
7 | import calfem.mesh as cfm
8 |
9 |
10 | # ---- Problem constants
11 |
12 | kx = 50
13 | ky = 50
14 | t = 1.0
15 | ep = [t]
16 |
17 | D = np.matrix([
18 | [kx, 0.],
19 | [0., ky]
20 | ])
21 |
22 | # ---- Problem geometry
23 |
24 | vertices = np.array([
25 | [0.0, 0.0],
26 | [200., 0.0],
27 | [200., 70.0],
28 | [120.0, 70.0],
29 | [120.0, 20.0],
30 | [80.0, 20.0],
31 | [80.0, 70.0],
32 | [0.0, 70.0]
33 | ])
34 |
35 | segments = np.array([
36 | [0,1,1],
37 | [1,2,1],
38 | [2,3,2],
39 | [3,4,1],
40 | [4,5,1],
41 | [5,6,1],
42 | [6,7,3],
43 | [7,0,1]
44 | ])
45 |
46 | # ---- Create element mesh
47 |
48 | print("Creating element mesh...")
49 |
50 | coords, edof, dofs, bdofs = cfm.trimesh2d(vertices, segments, maxArea=20.0, dofs_per_node=1)
51 |
52 | # ---- Assemble system matrix
53 |
54 | print("Assemblig system matrix...")
55 |
56 | nDofs = np.size(dofs)
57 | ex, ey = cfc.coordxtr(edof, coords, dofs)
58 |
59 | K = np.zeros([nDofs,nDofs])
60 |
61 | for eltopo, elx, ely in zip(edof, ex, ey):
62 | Ke = cfc.flw2te(elx, ely, ep, D)
63 | cfc.assem(eltopo, K, Ke)
64 |
65 | # ---- Solving equation system
66 |
67 | print("Solving equation system...")
68 |
69 | f = np.zeros([nDofs,1])
70 |
71 | bc = np.array([],'i')
72 | bcVal = np.array([],'i')
73 |
74 | bc, bcVal = cfu.applybc(bdofs,bc,bcVal,2,30.0)
75 | bc, bcVal = cfu.applybc(bdofs,bc,bcVal,3,0.0)
76 |
77 | a, r = cfc.solveq(K,f,bc,bcVal)
78 |
79 | # ---- Compute element forces
80 |
81 | print("Computing element forces...")
82 |
83 | ed = cfc.extractEldisp(edof,a)
84 | qs, qt = cfc.flw2ts(ex, ey, D, ed)
85 |
86 | # ---- Visualise results
87 |
88 | print("Drawing element mesh...")
89 |
90 | cfv.eliso2(ex,ey,ed)
91 | cfv.eldraw2(ex,ey)
92 | cfv.showAndWait()
93 |
94 | print("Done.")
95 |
96 |
97 |
98 |
99 |
--------------------------------------------------------------------------------
/examples/obsolete/extri2.py:
--------------------------------------------------------------------------------
1 | #!/bin/env python
2 |
3 | from calfem.core import *
4 | from calfem.utils import *
5 |
6 | def drawCustom(self, width, height):
7 | glPushMatrix()
8 | glBegin(GL_LINES)
9 | glColor(1.0, 0.0, 0.0, 1.0)
10 | glVertex(50,50,0)
11 | glVertex(100,100,0)
12 | glPopMatrix()
13 |
14 | # ---- Problem constants
15 |
16 | t = 0.1
17 | v = 0.35
18 | E = 2.1e9
19 | ptype = 1
20 | ep = [ptype,t]
21 |
22 | D=hooke(ptype, E, v)
23 |
24 | # ---- Problem geometry
25 |
26 | l = 0.2
27 | w = 0.05
28 | h = 0.1
29 |
30 | vertices = array([
31 | [0.0, h],
32 | [l, h],
33 | [l, 0.0],
34 | [l-w, 0.0],
35 | [l-w, h-w],
36 | [0.0, h-w]
37 | ])
38 |
39 | segments = array([
40 | [0,1,1],
41 | [1,2,1],
42 | [2,3,3],
43 | [3,4,1],
44 | [4,5,1],
45 | [5,0,2]
46 | ])
47 |
48 | # ---- Create element mesh
49 |
50 | print("Creating element mesh...")
51 |
52 | coords, edof, dofs, bdofs = trimesh2d(vertices, segments, maxArea=0.00005, dofsPerNode=2)
53 |
54 | # ---- Assemble system matrix
55 |
56 | print("Assemblig system matrix...")
57 |
58 | nDofs = size(dofs)
59 | ex, ey = coordxtr(edof, coords, dofs)
60 |
61 | #eldraw2(ex,ey)
62 |
63 | K = zeros([nDofs,nDofs])
64 |
65 | for eltopo, elx, ely in zip(edof, ex, ey):
66 | Ke = plante(elx, ely, ep, D)
67 | assem(eltopo, K, Ke)
68 |
69 | # ---- Solving equation system
70 |
71 | print("Solving equation system...")
72 |
73 | f = zeros([nDofs,1])
74 |
75 | bc = array([],'i')
76 | bcVal = array([],'i')
77 |
78 | bc, bcVal = applybc(bdofs,bc,bcVal,2,0.0)
79 | bc, bcVal = applybcnode(0, dofs, bc, bcVal, 0.0, 1)
80 | bc, bcVal = applybcnode(0, dofs, bc, bcVal, 0.0, 2)
81 | bc, bcVal = applybcnode(5, dofs, bc, bcVal, 0.0, 1)
82 | bc, bcVal = applybcnode(5, dofs, bc, bcVal, 0.0, 2)
83 |
84 | applyforce(bdofs,f,3,-10e3,2)
85 |
86 | a,r = solveq(K,f,bc,bcVal)
87 |
88 | # ---- Compute element forces
89 |
90 | print("Computing element forces...")
91 |
92 | ed = extractEldisp(edof,a)
93 | es, et = plants(ex, ey, ep, D, ed)
94 | ev = effmises(es, ptype)
95 | esnv = stress2nodal(ev, edof)
96 |
97 | # ---- Visualise results
98 |
99 | print("Drawing element mesh...")
100 |
101 | eldisp2(ex, ey, ed)
102 | elval2(ex, ey, ev)
103 | eliso2(ex, ey, esnv)
104 |
105 | elementView = ElementView(None, -1, "")
106 | elementView.ex = ex
107 | elementView.ey = ey
108 | elementView.ev = ev
109 | elementView.showMesh = False
110 | elementView.showElementValues = True
111 | elementView.showNodalValues = False
112 | elementView.drawCustom = drawCustom
113 | elementView.Show()
114 |
115 | waitDisplay()
116 |
117 | print("Done.")
118 |
119 |
120 |
121 |
--------------------------------------------------------------------------------
/gen_output_dict.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | This script generates a dictionary of example outputs.
4 | """
5 |
6 | import os, sys, re, subprocess
7 | from pprint import pprint
8 |
9 | def extract_numeric_values(output_text):
10 | """Extract numeric values from output text using regex."""
11 | import re
12 | pattern = r'[-+]?\d*\.\d+(?:[eE][-+]?\d+)?'
13 | return [float(x) for x in re.findall(pattern, output_text)]
14 |
15 | def compare_outputs(output1, output2, rtol=1e-5, atol=1e-8):
16 | """Compare outputs with tolerance."""
17 | import numpy as np
18 | values1 = extract_numeric_values(output1)
19 | values2 = extract_numeric_values(output2)
20 |
21 | if len(values1) != len(values2):
22 | return False
23 |
24 | return np.allclose(values1, values2, rtol=rtol, atol=atol)
25 |
26 | def gen_output_examples():
27 |
28 | examples_dir = "examples"
29 |
30 | examples = [
31 | "exs_bar2.py",
32 | "exs_bar2_la.py",
33 | "exs_bar2_lb.py",
34 | "exs_beam1.py",
35 | "exs_beam2.py",
36 | "exs_beambar2.py",
37 | "exs_flw_diff2.py",
38 | "exs_flw_temp1.py",
39 | "exs_flw_temp2.py",
40 | "exs_spring.py",
41 | "exm_stress_2d_materials.py",
42 | "exm_stress_2d.py",
43 | "exm_flow_model.py",
44 | ]
45 |
46 | # Set environment variable to avoid blocking of plots
47 |
48 |
49 | os.environ["CFV_NO_BLOCK"] = "YES"
50 | env = os.environ.copy()
51 |
52 | # Assume 0 return codes
53 |
54 | return_codes = 0
55 |
56 | example_dict = {}
57 |
58 | for example in examples:
59 | print(f"Running: {example}")
60 |
61 | proc = subprocess.run(
62 | [sys.executable, f"examples/{example}"],
63 | env=env,
64 | capture_output=True,
65 | text=True
66 | )
67 |
68 | # Check return code
69 | assert proc.returncode == 0, f"Example {example} failed with output: {proc.stderr}"
70 |
71 | actual_values = extract_numeric_values(proc.stdout)
72 |
73 | example_dict[example] = actual_values
74 |
75 |
76 | # Save the example dictionary to a file
77 |
78 | with open("example_outputs.py", "w") as f:
79 | f.write("# Example outputs\n")
80 | f.write("examples = {\n")
81 | for example, values in example_dict.items():
82 | f.write(f" '{example}': {values},\n")
83 | f.write("}\n")
84 |
85 | if __name__ == "__main__":
86 | gen_output_examples()
--------------------------------------------------------------------------------
/pyproject.toml:
--------------------------------------------------------------------------------
1 | [project]
2 | name = "calfem-python"
3 | version = "3.6.11"
4 | description = "CALFEM for Python"
5 | authors = [
6 | {name = "Jonas Lindemann", email = "jonas.lindemann@lunarc.lu.se"},
7 | {name = "Jonas Lindemann", email = "jonas.lindemann@gmail.com"},
8 | ]
9 | dependencies = [
10 | "gmsh",
11 | "matplotlib",
12 | "numpy < 2",
13 | "scipy",
14 | "tabulate",
15 | ]
16 |
17 | requires-python = ">=3.8"
18 | readme = "README.md"
19 | license = {text = "MIT"}
20 | keywords = [
21 | "finite element",
22 | "math",
23 | "numerics",
24 | ]
25 | classifiers = [
26 | "Development Status :: 4 - Beta",
27 | "Intended Audience :: Developers",
28 | "License :: OSI Approved :: MIT License",
29 | "Programming Language :: Python :: 3",
30 | "Programming Language :: Python :: 3.10",
31 | "Programming Language :: Python :: 3.11",
32 | "Programming Language :: Python :: 3.12",
33 | "Programming Language :: Python :: 3.7",
34 | "Programming Language :: Python :: 3.8",
35 | "Programming Language :: Python :: 3.9",
36 | "Topic :: Software Development :: Build Tools",
37 | ]
38 |
39 | [project.urls]
40 | Homepage = "https://github.com/CALFEM/calfem-python"
41 | [build-system]
42 | requires = ["pdm-backend"]
43 | build-backend = "pdm.backend"
44 |
45 | [tool.pdm]
46 | distribution = true
47 |
48 | [project.optional-dependencies]
49 | visvis = [ "visvis" ]
50 | vedo = [ "vedo" ]
51 | pyvtk = [ "pyvtk" ]
52 | qtpy = [ "qtpy" ]
53 |
--------------------------------------------------------------------------------
/reports/manual-mesh-module.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/reports/manual-mesh-module.pdf
--------------------------------------------------------------------------------
/reports/manual.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/reports/manual.pdf
--------------------------------------------------------------------------------
/resources/resources.qrc:
--------------------------------------------------------------------------------
1 |
2 |
3 | blank.svg
4 | plus.svg
5 | minus.svg
6 | erase.png
7 | add_marker.svg
8 | merge.svg
9 | split_edge.svg
10 | polygon.svg
11 | polygon_hole.svg
12 | rectangle.svg
13 | rectangle_hole.svg
14 | rectangle.svg
15 | polygon_hole.svg
16 | rectangle_hole.svg
17 | polygon.svg
18 | geometry.png
19 | grid.png
20 | grid_settings.png
21 | grid_snap.png
22 | line.png
23 | line_number.png
24 | move.png
25 | move_node.png
26 | node.png
27 | node_number.png
28 | save.png
29 | zoom_in.png
30 | zoom_out.png
31 | pan.png
32 | open.png
33 | polygon_hole.svg
34 | select.png
35 |
36 |
37 |
38 |
39 |
--------------------------------------------------------------------------------
/src/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/src/__init__.py
--------------------------------------------------------------------------------
/src/calfem/__init__.py:
--------------------------------------------------------------------------------
1 | __version__ = '3.6.1'
2 | VERSION = __version__
3 |
--------------------------------------------------------------------------------
/src/calfem/_export.py:
--------------------------------------------------------------------------------
1 | import pickle
2 | import scipy.io
3 | import numpy as np
4 |
5 | '''
6 | Handle reading and writing of geometry and generated mesh from the program
7 | '''
8 |
9 |
10 | def loadGeometry(name):
11 | with open(name, 'rb') as file:
12 | test = pickle.load(file)
13 | return test
14 |
15 |
16 | def saveGeometry(g, name="Untitled"):
17 | if not name.endswith(".cfg"):
18 | name = name + ".cfg"
19 | with open(name, 'wb') as file:
20 | pickle.dump(g, file)
21 |
22 |
23 | def loadMesh(name):
24 | with open(name, 'rb') as file:
25 | mesh = pickle.load(file)
26 | return mesh
27 |
28 |
29 | def saveMesh(mesh, name="Untitled"):
30 | if not name.endswith(".cfm"):
31 | name = name + ".cfm"
32 | with open(name, 'wb') as file:
33 | pickle.dump(mesh, file)
34 |
35 |
36 | def saveArrays(coords, edof, dofs, bdofs, elementmarkers, boundaryElements, markerDict ,name="Untitled"):
37 | if not name.endswith(".cfma"):
38 | name = name + ".cfma"
39 | with open(name, 'wb') as file:
40 | pickle.dump(coords, file)
41 | pickle.dump(edof, file)
42 | pickle.dump(dofs, file)
43 | #for key in bdofs.items():
44 | # print(key, markerDict[key])
45 | pickle.dump(bdofs, file)
46 | pickle.dump(elementmarkers, file)
47 | pickle.dump(boundaryElements, file)
48 | pickle.dump(markerDict, file)
49 |
50 |
51 | def loadArrays(name):
52 | with open(name, 'rb') as file:
53 | coords = pickle.load(file)
54 | edof= pickle.load(file)
55 | dofs = pickle.load(file)
56 | bdofs = pickle.load(file)
57 | elementmarkers = pickle.load(file)
58 | boundaryElements = pickle.load(file)
59 | markerDict = pickle.load(file)
60 |
61 | return coords, edof, dofs, bdofs, elementmarkers, boundaryElements, markerDict
62 |
63 |
64 | def saveMatlabArrays(coords, edof, dofs, bdofs, elementmarkers, boundaryElements, markerDict, name="Untitled"):
65 | if not name.endswith(".mat"):
66 | name = name + ".mat"
67 | saveDict = {}
68 | saveDict["coords"] = coords.astype('double')
69 | # Convert to CALFEM Edof definition with element number as first index
70 | new_column = np.arange(1, np.size(edof, 0) + 1)[:, np.newaxis]
71 | edof = np.append(new_column, edof, axis=1)
72 |
73 | saveDict["edof"] = edof.astype('double')
74 | saveDict["dofs"] = dofs.astype('double')
75 | # bdofs = {str(k): v for k, v in bdofs.items()} # MATLAB struct needs keys as strings
76 | #print(markerDict)
77 | newBdof = {}
78 | for name, index in bdofs.items():
79 | print(name, index)
80 | if index == 0:
81 | newBdof["None"] = 0
82 | else:
83 | newBdof[markerDict[index]] = name
84 |
85 | saveDict["bdofs"] = newBdof
86 | elementmarkers = np.asarray(elementmarkers)
87 | elementmarkers = elementmarkers + 1 # To avoid problems with one indexing in MATLAB
88 | saveDict["elementmarkers"] = elementmarkers
89 | scipy.io.savemat(name, saveDict)
90 |
91 |
--------------------------------------------------------------------------------
/src/calfem/intvis.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | import sys
4 |
5 | from qtpy.QtWidgets import *
6 | from qtpy.QtGui import *
7 |
8 | import calfem.ui as cfui
9 |
10 | class GuiWindow(QWidget):
11 | def __init__(self, var_dict):
12 | """MyWindow constructor"""
13 |
14 | super().__init__()
15 |
16 | # Skapa gränssnittskontroller
17 |
18 | self.var_dict = var_dict
19 |
20 | self.init_gui()
21 |
22 | def __parse_variables(self, g):
23 |
24 | # a_edit = 1
25 | # b_slider = 2.0
26 | # c_list = [1, 2, 3]
27 | # d_check = True
28 | # f_param = 42.0
29 | # g_float = 84.0
30 | # g_int = 34
31 |
32 | row = 0
33 |
34 | for key, value in self.var_dict.items():
35 | if '_edit' in key:
36 | var_label = QLabel(key)
37 | var_edit = QLineEdit(str(value))
38 |
39 | g.addWidget(var_label, row, 0)
40 | g.addWidget(var_edit, row, 1)
41 | elif '_slider' in key:
42 | var_label = QLabel(key.split("_")[0])
43 | var_edit = QSlider()
44 |
45 |
46 | def init_gui(self):
47 | """Initiera gränssnitt"""
48 |
49 | self.setGeometry(300, 300, 600, 600)
50 | self.setWindowTitle("Parameter window")
51 |
52 | self.grid = QGridLayout(self)
53 |
54 | row = 0
55 |
56 | for key, value in self.var_dict.items():
57 | var_label = QLabel(key)
58 | var_edit = QLineEdit(str(value))
59 |
60 | self.grid.addWidget(var_label, row, 0)
61 | self.grid.addWidget(var_edit, row, 1)
62 |
63 | row += 1
64 |
65 | buttons = QHBoxLayout()
66 |
67 | ok_button = QPushButton("OK")
68 | cancel_button = QPushButton("Cancel")
69 |
70 | buttons.addStretch()
71 | buttons.addWidget(ok_button)
72 | buttons.addWidget(cancel_button)
73 | buttons.addStretch()
74 |
75 | self.grid.setRowStretch(row, 10)
76 |
77 | row += 1
78 |
79 | self.grid.addLayout(buttons, row, 0, 1, 2)
80 |
81 | # Visa fönster
82 |
83 | self.show()
84 |
85 | def create_window(var_dict):
86 | w = GuiWindow(var_dict)
87 |
88 | return w
89 |
90 | def parse_variables(var_dict):
91 | """Parse variables in current context"""
92 | valid_vars = {}
93 |
94 | for key, value in var_dict.items():
95 | if type(value) is int:
96 | valid_vars[key] = value
97 | if type(value) is float:
98 | valid_vars[key] = value
99 | if type(value) is list:
100 | valid_vars[key] = value
101 | if type(value) is bool:
102 | valid_vars[key] = value
103 |
104 | return valid_vars
105 |
106 | def edit_params(var_dict):
107 | """Run Qt event loop"""
108 |
109 | valid_vars = parse_variables(var_dict)
110 | print(valid_vars)
111 |
112 | app = cfui.init_qt_app()
113 |
114 | # Skapa vårt MyWindow objekt
115 |
116 | w = create_window(valid_vars)
117 | w.show()
118 |
119 | # Starta händelseloop
120 |
121 | app.exec_()
122 |
123 | def edit_geometry(geometry):
124 | pass
--------------------------------------------------------------------------------
/src/calfem/misc.py:
--------------------------------------------------------------------------------
1 | def mlscalar2d(coords, edof, a):
2 | if not haveMlab:
3 | return
4 |
5 | x = reshape(coords[:,0],[size(coords[:,0])])
6 | y = reshape(coords[:,1],[size(coords[:,1])])
7 | z = zeros([size(coords[:,0])])
8 | ascalar = reshape(asarray(a),[size(a)])
9 |
10 | mlab.triangular_mesh(x, y, z, edof-1, scalars=ascalar, representation="surface")
11 |
12 | def mlflux2d(coords, vf, scalefactor=None, displaymode="2darrow"):
13 | if not haveMlab:
14 | return
15 |
16 | x = reshape(coords[:,0],[size(coords[:,0])])
17 | y = reshape(coords[:,1],[size(coords[:,1])])
18 | z = zeros([size(coords[:,0])])
19 | u = reshape(vf[:,0],[size(vf[:,0])])
20 | v = reshape(vf[:,1],[size(vf[:,1])])
21 | w = zeros([size(vf[:,0])])
22 |
23 | if scalefactor == None:
24 | mlab.quiver3d(x, y, z, u, v, w, mode=displaymode)
25 | else:
26 | mlab.quiver3d(x, y, z, u, v, w, mode=displaymode, scale_factor=scalefactor)
27 |
28 |
29 | def mlwireframe2d(coords, edof):
30 | if not haveMlab:
31 | return
32 |
33 | x = reshape(coords[:,0],[size(coords[:,0])])
34 | y = reshape(coords[:,1],[size(coords[:,1])])
35 | z = zeros([size(coords[:,0])])+1
36 | scalars = ones([size(coords[:,0])])
37 |
38 | mlab.triangular_mesh(x, y, z, edof-1, scalars=scalars, representation="mesh", colormap="bone", line_width=20.0)
39 |
40 |
41 | def eldisp2(ex,ey,ed,rat=0.2):
42 | nen = -1
43 | if ex.shape != ey.shape:
44 | print("ex and ey shapes do not match.")
45 | return 1.0
46 |
47 | dlmax = 0.
48 | edmax = 1.
49 |
50 | # print(rank(ex))
51 |
52 | if np.linalg.matrix_rank(ex)==1:
53 | nen = ex.shape[0]
54 | nel = 1
55 | dxmax = max(ex.T.max(0)-ex.T.min(0))
56 | dymax = max(ey.T.max(0)-ey.T.min(0))
57 | dlmax = max(dxmax,dymax)
58 | edmax = abs(ed).max()
59 | else:
60 | nen = ex.shape[1]
61 | nel = ex.shape[0]
62 | dxmax = max(ex.T.max(0)-ex.T.min(0))
63 | dymax = max(ey.T.max(0)-ey.T.min(0))
64 | dlmax = max(dxmax,dymax)
65 | edmax = abs(ed).max()
66 |
67 | k = rat
68 | return k*dlmax/edmax
69 |
--------------------------------------------------------------------------------
/src/calfem/qt5.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | Created on Wed Apr 12 23:17:26 2017
4 |
5 | @author: jonas_000
6 | """
7 |
8 | from qtpy.QtCore import Slot, Signal, QMetaObject
9 | from qtpy.QtWidgets import *
10 | from qtpy.QtGui import QPixmap
11 | from qtpy.uic import loadUi
12 |
--------------------------------------------------------------------------------
/src/calfem/shapes.py:
--------------------------------------------------------------------------------
1 | import numpy as np
2 | import calfem.core as cfc
3 | import calfem.geometry as cfg
4 | import calfem.mesh as cfm
5 | import calfem.vis as cfv
6 |
7 | import logging as cflog
8 |
9 | def error(msg):
10 | cflog.error("calfem.shapes: "+msg)
11 |
12 | def info(msg):
13 | cflog.info("calfem.shapes: "+msg)
14 |
15 |
16 | class Shape:
17 | """Base class for shapes"""
18 |
19 | def __init__(self, element_type = 3, dofs_per_node = 1, max_area = 1.0):
20 | self.max_area = max_area
21 | self.element_type = element_type
22 | self.dofs_per_node = dofs_per_node
23 |
24 | def geometry(self):
25 | """Return geometry of shape"""
26 | return None
27 |
28 |
29 |
30 | class Rectangle(Shape):
31 | """Rectangle geometry"""
32 |
33 | def __init__(self, width=1.0, height=1.0, element_type = 3, dofs_per_node = 1, max_area = -1):
34 | Shape.__init__(self, element_type, dofs_per_node, max_area)
35 | self.width = width
36 | self.height = height
37 |
38 | if (max_area<0):
39 | self.max_area = self.width * self.height * 0.05
40 | else:
41 | self.max_area = max_area
42 |
43 | self.left_id = 101
44 | self.right_id = 102
45 | self.top_id = 103
46 | self.bottom_id = 104
47 |
48 | def geometry(self):
49 | """Return geometry of shape"""
50 | self.g = cfg.Geometry()
51 |
52 | w = self.width
53 | h = self.height
54 |
55 | self.g.point([0, 0])
56 | self.g.point([w, 0])
57 | self.g.point([w, h])
58 | self.g.point([0, h])
59 |
60 | self.g.spline([0, 1], marker=self.bottom_id)
61 | self.g.spline([1, 2], marker=self.right_id)
62 | self.g.spline([2, 3], marker=self.top_id)
63 | self.g.spline([3, 0], marker=self.left_id)
64 |
65 | self.g.surface([0,1,2,3])
66 |
67 | return self.g
68 |
69 | class RectangleWithHole(Rectangle):
70 | def __init__(self, width=1.0, height=1.0, element_type = 3, dofs_per_node = 1, max_area = -1):
71 | super().__init__(self, width, height, element_type, dofs_per_node, max_area)
72 |
73 | class ShapeMesh:
74 | """Mesh generator for shapes"""
75 | def __init__(self, shape):
76 | """Initialise mesh generator"""
77 | self.shape = shape
78 |
79 | self.create()
80 |
81 | def create(self):
82 | meshGen = cfm.GmshMeshGenerator(self.shape.geometry())
83 | meshGen.el_type = self.shape.element_type
84 | meshGen.el_size_factor = self.shape.max_area
85 | meshGen.dofs_per_node = self.shape.dofs_per_node
86 |
87 | self.coords, self.edof, self.dofs, self.bdofs, self.markers = meshGen.create()
88 |
89 | # --- Beräkna element koordinater
90 |
91 | self.ex, self.ey = cfc.coordxtr(self.edof, self.coords, self.dofs)
92 | self.pointDofs = self.dofs[list(self.shape.g.points.keys()),:]
93 |
94 | if __name__ == "__main__":
95 |
96 |
97 | print("Creating rectangle")
98 | rect = Rectangle(5.0, 1.0, element_type=3, dofs_per_node=2, max_area=0.05)
99 |
100 | print("Creating mesh...")
101 |
102 | mesh = ShapeMesh(rect)
103 |
104 | print(mesh.edof)
105 | print(mesh.dofs)
106 | print(mesh.bdofs[rect.left_id])
107 | print(mesh.bdofs[rect.right_id])
108 | print(mesh.bdofs[rect.top_id])
109 | print(mesh.bdofs[rect.bottom_id])
110 | print(mesh.pointDofs)
111 |
--------------------------------------------------------------------------------
/src/calfem/ui.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | CALFEM UI module
4 |
5 | Routines for interfacing wirt user interface toolkits.
6 | """
7 |
8 | import os, sys
9 |
10 | print("------------------------------------")
11 | print("CALFEM/Python ui module initialising")
12 | print("------------------------------------")
13 | print()
14 |
15 | from qtpy.QtCore import Slot, Signal, QThread
16 | from qtpy.QtWidgets import QApplication, QDialog, QWidget, QMainWindow
17 | from qtpy.QtGui import QPixmap
18 | from qtpy.uic import loadUi
19 |
20 | g_inSpyder = False
21 |
22 | if any('SPYDER' in name for name in os.environ):
23 | print('Running in Spyder...')
24 | g_inSpyder = True
25 |
26 | g_haveVisVis = True
27 |
28 | try:
29 | import visvis as vv
30 | except:
31 | g_haveVisVis = False
32 |
33 | if g_haveVisVis:
34 | print("VisVis installed...")
35 | else:
36 | print("VisVis not installed...")
37 |
38 | def init_qt_app():
39 | app = QApplication.instance()
40 |
41 | if app is None:
42 | print("No QApplication instance found. Creating one.")
43 | # if it does not exist then a QApplication is created
44 | app = QApplication(sys.argv)
45 | else:
46 | print("QApplication instance found. Reusing.")
47 |
48 | return app
49 |
50 | def loadUiWidget(uifilename, parent=None):
51 | """Load user interface file and return object model"""
52 | ui = loadUi(uifilename, parent)
53 | return ui
54 |
55 | load_ui_widget = loadUiWidget
56 |
57 | def appInstance(useVisVis=True):
58 | """Create a suitable application instance"""
59 | print("Creating application instance...")
60 |
61 | global g_haveVisVis
62 |
63 | app = None
64 |
65 | if g_haveVisVis and useVisVis:
66 | print("Using VisVis application instance...")
67 | app = vv.use()
68 | app.Create()
69 | else:
70 | print("Trying Qt application instance...")
71 | app = QtGui.QApplication.instance()
72 | if app is None:
73 | print("Creating new Qt application instance...")
74 | app = QtGui.QApplication(sys.argv)
75 | else:
76 | print("Reusing existing Qt application instance...")
77 |
78 | if app!=None:
79 | app.Run = app.exec_
80 |
81 | if app is None:
82 | print("No application instance found. Exiting...")
83 | sys.exit(-1)
84 |
85 | return app
86 |
87 | app_instance = appInstance
--------------------------------------------------------------------------------
/src/calfem/vis_vtk.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | CALFEM Visualisation module (matplotlib)
4 |
5 | Contains all the functions implementing visualisation routines.
6 | """
7 |
8 | import vtk
9 |
10 | def draw_mesh(coords, edof, el_type):
11 |
12 | colors = vtk.vtkNamedColors()
13 | points = vtk.vtkPoints()
14 |
15 | for i, coord in enumerate(coords):
16 | points.InsertPoint(i, coord)
17 |
18 | ugrid = vtk.vtkUnstructuredGrid()
19 | ugrid.Allocate(edof.shape[0])
20 |
21 | for dofs in edof:
22 | if (el_type == 4):
23 | ugrid.InsertNextCell(vtk.VTK_TETRA, 4, dofs-1)
24 | elif (el_type == 5):
25 | ugrid.InsertNextCell(vtk.VTK_HEXAHEDRON, 8, dofs-1)
26 | else:
27 | print("Unsupported element type.")
28 |
29 | ugrid.SetPoints(points)
30 |
31 | ugridMapper = vtk.vtkDataSetMapper()
32 | ugridMapper.SetInputData(ugrid)
33 |
34 | ugridActor = vtk.vtkActor()
35 | ugridActor.SetMapper(ugridMapper)
36 | ugridActor.GetProperty().SetColor(colors.GetColor3d('Peacock'))
37 | ugridActor.GetProperty().EdgeVisibilityOn()
38 |
39 | renderer = vtk.vtkRenderer()
40 |
41 | renWin = vtk.vtkRenderWindow()
42 | renWin.AddRenderer(renderer)
43 | iren = vtk.vtkRenderWindowInteractor()
44 | iren.SetRenderWindow(renWin)
45 |
46 | renderer.AddActor(ugridActor)
47 | renderer.SetBackground(colors.GetColor3d('Beige'))
48 |
49 | renderer.ResetCamera()
50 | renderer.GetActiveCamera().Elevation(60.0)
51 | renderer.GetActiveCamera().Azimuth(30.0)
52 | renderer.GetActiveCamera().Dolly(1.0)
53 |
54 | renWin.SetSize(640, 480)
55 | renWin.SetWindowName('UGrid')
56 |
57 | # Interact with the data.
58 | renWin.Render()
59 |
60 | iren.Start()
61 |
62 |
63 |
--------------------------------------------------------------------------------
/test_calfem.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 | """
3 | This is very simple test of the calfem package.
4 |
5 | Make sure all examples run without errors.
6 | """
7 |
8 | import os, sys, re, subprocess
9 | import example_outputs as eo
10 | import numpy as np
11 |
12 | from pprint import pprint
13 |
14 | def extract_numeric_values(output_text):
15 | """Extract numeric values from output text using regex."""
16 | import re
17 | pattern = r'[-+]?\d*\.\d+(?:[eE][-+]?\d+)?'
18 | return [float(x) for x in re.findall(pattern, output_text)]
19 |
20 | def compare_outputs(output1, output2, rtol=1e-5, atol=1e-8):
21 | """Compare outputs with tolerance."""
22 | import numpy as np
23 | values1 = extract_numeric_values(output1)
24 | values2 = extract_numeric_values(output2)
25 |
26 | if len(values1) != len(values2):
27 | return False
28 |
29 | return np.allclose(values1, values2, rtol=rtol, atol=atol)
30 |
31 | def test_examples():
32 |
33 | examples_dir = "examples"
34 |
35 | examples = [
36 | "exs_bar2.py",
37 | "exs_bar2_la.py",
38 | "exs_bar2_lb.py",
39 | "exs_beam1.py",
40 | "exs_beam2.py",
41 | "exs_beambar2.py",
42 | "exs_flw_diff2.py",
43 | "exs_flw_temp1.py",
44 | "exs_flw_temp2.py",
45 | "exs_spring.py",
46 | "exm_stress_2d.py",
47 | "exm_stress_2d_materials.py",
48 | "exm_flow_model.py"
49 | ]
50 |
51 | # Set environment variable to avoid blocking of plots
52 |
53 | os.environ["CFV_NO_BLOCK"] = "YES"
54 |
55 | # Assume 0 return codes
56 |
57 | for example in examples:
58 | print(f"Running: {example} ", end="")
59 |
60 | env = os.environ.copy()
61 | env["CFV_NO_BLOCK"] = "YES"
62 |
63 | proc = subprocess.run(
64 | [sys.executable, f"examples/{example}"],
65 | env=env,
66 | capture_output=True,
67 | text=True
68 | )
69 |
70 | # Check return code
71 | assert proc.returncode == 0, f"Example {example} failed with output: {proc.stderr}"
72 |
73 | # Compare numeric values within tolerance
74 | actual_values = extract_numeric_values(proc.stdout)
75 | expected_values = eo.examples[example]
76 |
77 | assert len(actual_values) == len(expected_values), \
78 | f"Expected {len(expected_values)} values, got {len(actual_values)}"
79 |
80 | assert np.allclose(actual_values, expected_values, rtol=1e-5, atol=1e-8), \
81 | "Numeric values differ significantly"
82 |
83 | print(f"PASSED.")
84 |
85 | if __name__ == "__main__":
86 | test_examples()
87 |
--------------------------------------------------------------------------------
/tests/__init__.py:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/CALFEM/calfem-python/a6a71e4e031bd6f15922089d993245ca3726d155/tests/__init__.py
--------------------------------------------------------------------------------