├── .git-blame-ignore-revs ├── .github ├── CODEOWNERS ├── azure-pipelines.yaml ├── build_real.sh └── test_real.sh ├── .gitignore ├── .readthedocs.yaml ├── Common.mk ├── LICENSE.md ├── Makefile ├── README.md ├── Rules.mk ├── config └── defaults │ ├── config.LINUX_GFORTRAN.mk │ ├── config.LINUX_INTEL.mk │ └── config.OSX_GFORTRAN.mk ├── doc ├── API │ ├── curve.rst │ ├── surface.rst │ ├── utils.rst │ └── volume.rst ├── Makefile ├── conf.py ├── example_curve.rst ├── example_surface.rst ├── example_volume.rst ├── examples.rst ├── index.rst ├── install.rst ├── make.bat └── requirements.txt ├── examples ├── example_curve.py ├── example_surf.py ├── example_volume.py ├── helix.lay ├── naca.lay ├── naca0012 ├── projections.lay ├── surface.lay └── volume.lay ├── lib └── Makefile ├── mod └── README ├── pyspline ├── __init__.py ├── pyCurve.py ├── pySurface.py ├── pyVolume.py └── utils.py ├── setup.py ├── src ├── Makefile ├── adtProjections.F90 ├── basis.f90 ├── compute_curve.f90 ├── compute_surface.f90 ├── compute_volume.f90 ├── eval_curve.f90 ├── eval_surface.f90 ├── eval_volume.f90 ├── evaluations.f90 ├── f2py │ ├── Makefile │ ├── f2py_f2cmap.ref │ ├── get_f2py.py │ ├── importTest.py │ └── pyspline.pyf ├── findSpan.f90 ├── getBasisPt.f90 ├── insertKnot.f90 ├── knots.f90 ├── parameterizations.f90 ├── precision.f90 ├── projections.F90 └── tfi2d.f90 └── tests └── reg_tests ├── ref ├── test_curves.ref ├── test_surfaces.ref └── test_volumes.ref ├── test_curves.py ├── test_surfaces.py └── test_volumes.py /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # fprettify 2 | 03a66910555dc5d0ba28c74a69dd36438981d0d7 3 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | * @mdolab/pyspline_maintainers 2 | -------------------------------------------------------------------------------- /.github/azure-pipelines.yaml: -------------------------------------------------------------------------------- 1 | trigger: 2 | - main 3 | 4 | pr: 5 | - main 6 | 7 | resources: 8 | repositories: 9 | - repository: azure_template 10 | type: github 11 | name: mdolab/.github 12 | endpoint: mdolab 13 | 14 | extends: 15 | template: azure/azure_template.yaml@azure_template 16 | parameters: 17 | REPO_NAME: pyspline 18 | GCC_CONFIG: config/defaults/config.LINUX_GFORTRAN.mk 19 | INTEL_CONFIG: config/defaults/config.LINUX_INTEL.mk 20 | ISORT: true 21 | COVERAGE: true 22 | FPRETTIFY: true 23 | -------------------------------------------------------------------------------- /.github/build_real.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | cp $CONFIG_FILE config/config.mk 4 | make 5 | pip install . 6 | -------------------------------------------------------------------------------- /.github/test_real.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | set -e 3 | 4 | cd tests 5 | testflo -v --coverage --coverpkg pyspline 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # use glob syntax. 2 | syntax: glob 3 | doc/_build/* 4 | *.o 5 | *.pyc 6 | *.~ 7 | *.dat 8 | *.orig 9 | *~ 10 | *.a 11 | *.mod 12 | *.so 13 | *.out 14 | *.egg-info 15 | config.mk 16 | config/config.mk 17 | src/f2py/libspline-f2pywrappers2.f90 18 | *.DS_Store 19 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | version: 2 6 | 7 | build: 8 | os: ubuntu-22.04 9 | tools: 10 | python: "3.11" 11 | 12 | sphinx: 13 | configuration: doc/conf.py 14 | 15 | python: 16 | install: 17 | - requirements: doc/requirements.txt 18 | -------------------------------------------------------------------------------- /Common.mk: -------------------------------------------------------------------------------- 1 | # Common Makefile for : 2 | 3 | MODDIR = $(MAIN_DIR)/mod 4 | OBJDIR = $(MAIN_DIR)/obj 5 | LIBDIR = $(MAIN_DIR)/lib 6 | 7 | # ****************************************************************** 8 | # * * 9 | # * Include the file describing the compiler settings. * 10 | # * * 11 | # ****************************************************************** 12 | 13 | MAKE = make 14 | 15 | COMPILERS = $(MAIN_DIR)/config.mk 16 | ifneq ($(MAKECMDGOALS),clean) 17 | include ${COMPILERS} 18 | endif 19 | 20 | # ****************************************************************** 21 | # * * 22 | # * Redefine .SUFFIXES to be sure all the desired ones are * 23 | # * included. * 24 | # * * 25 | # ****************************************************************** 26 | 27 | .SUFFIXES: .o .f .F .f90 .F90 28 | 29 | # ****************************************************************** 30 | # * * 31 | # * Arguments of make clean. * 32 | # * * 33 | # ****************************************************************** 34 | 35 | MAKE_CLEAN_ARGUMENTS = *~ *.o *.mod *.il *.stb c_* *.so 36 | 37 | # ****************************************************************** 38 | # * * 39 | # * Compiler flags to compile the sources. * 40 | # * The macro's ADDITIONAL_FF90_FLAGS and ADDITIONAL_CC_FLAGS * 41 | # * make it possible that every subdirectory adds its own specific * 42 | # * compiler flags, if necessary. * 43 | # * * 44 | # ****************************************************************** 45 | 46 | FF90_ALL_FLAGS = -I$(MODDIR) $(FF90_FLAGS) 47 | CC_ALL_FLAGS = -I$(MODDIR) $(CC_FLAGS) 48 | 49 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | # pySpline 2 | 3 | pySpline is a package for handling B-splines. 4 | ______________________________________________________________________________ 5 | 6 | Copyright (c) 2014 University of Michigan\ 7 | Additional copyright (c) 2014 Gaetan K. W. Kenway and Joaquim R. R. A. Martins\ 8 | All rights reserved. 9 | ______________________________________________________________________________ 10 | 11 | pySpline is licensed under the Apache License, Version 2.0 (the "License"); you may not use this software except in compliance with the License. You may obtain a copy of the License at:\ 12 | http://www.apache.org/licenses/LICENSE-2.0 13 | ______________________________________________________________________________ 14 | 15 | University of Michigan's Multidisciplinary Design Optimization Laboratory (MDO Lab)\ 16 | College of Engineering, Aerospace Engineering Department\ 17 | http://mdolab.engin.umich.edu/ 18 | ______________________________________________________________________________ 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for pySpline 2 | 3 | SUBDIR_SRC = src/ 4 | 5 | default: 6 | # Check if the config.mk file is in the config dir. 7 | @if [ ! -f "config/config.mk" ]; then \ 8 | echo "Before compiling, copy an existing config file from the "; \ 9 | echo "config/defaults/ directory to the config/ directory and "; \ 10 | echo "rename to config.mk. For example:"; \ 11 | echo " ";\ 12 | echo " cp config/defaults/config.LINUX_INTEL.mk config/config.mk"; \ 13 | echo " ";\ 14 | echo "The modify this config file as required. With the config file specified, rerun "; \ 15 | echo "'make' and the build will start"; \ 16 | else make module;\ 17 | fi; 18 | 19 | clean: 20 | @echo " Making clean ... " 21 | @for subdir in $(SUBDIR_SRC) ; \ 22 | do \ 23 | echo; \ 24 | echo "making $@ in $$subdir"; \ 25 | echo; \ 26 | (cd $$subdir && make $@) || exit 1; \ 27 | done 28 | rm -f *~ config.mk; 29 | rm -f lib/lib* mod/*.mod obj/* 30 | 31 | module: 32 | mkdir -p obj 33 | ln -sf config/config.mk config.mk 34 | @for subdir in $(SUBDIR_SRC) ; \ 35 | do \ 36 | echo "making $@ in $$subdir"; \ 37 | echo; \ 38 | (cd $$subdir && make) || exit 1; \ 39 | done 40 | (cd lib && make) 41 | (cd src/f2py && make) 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | pySpline 2 | ==================================================== 3 | [![Build Status](https://dev.azure.com/mdolab/Public/_apis/build/status/mdolab.pyspline?branchName=main)](https://dev.azure.com/mdolab/Public/_build/latest?definitionId=20&branchName=main) 4 | [![Documentation Status](https://readthedocs.com/projects/mdolab-pyspline/badge/?version=latest)](https://mdolab-pyspline.readthedocs-hosted.com/en/latest/?badge=latest) 5 | [![codecov](https://codecov.io/gh/mdolab/pyspline/branch/main/graph/badge.svg?token=J1DDOBHVRT)](https://codecov.io/gh/mdolab/pyspline) 6 | 7 | ``pySpline`` is a package containing code for wiking with b-spline 8 | ``curve``, ``surface``, and ``volume`` objects. The 9 | Python interface to all functionality is found in the pySpline.py 10 | module. 11 | 12 | Documentation 13 | ------------- 14 | 15 | Please see the [documentation](https://mdolab-pyspline.readthedocs-hosted.com/en/latest/) for installation details and API documentation. 16 | 17 | To locally build the documentation, enter the `doc` folder and enter `make html` in terminal. 18 | You can then view the built documentation in the `_build` folder. 19 | 20 | 21 | Citation 22 | -------- 23 | 24 | Please cite pySpline in any publication for which you find it useful. 25 | For more background, theory, and figures, see the [pyGeo journal article](http://mdolab.engin.umich.edu/sites/default/files/mao2010_final.pdf). 26 | 27 | G. K. W. Kenway, Kennedy, G. J., and Martins, J. R. R. A., “A CAD-Free Approach to High-Fidelity Aerostructural Optimization”, in Proceedings of the 13th AIAA/ISSMO Multidisciplinary Analysis Optimization Conference, Fort Worth, TX, 2010. 28 | 29 | ``` 30 | @conference {Kenway:2010:C, 31 | title = {A {CAD}-Free Approach to High-Fidelity Aerostructural Optimization}, 32 | booktitle = {Proceedings of the 13th AIAA/ISSMO Multidisciplinary Analysis Optimization Conference}, 33 | year = {2010}, 34 | note = {AIAA 2010-9231}, 35 | month = {September}, 36 | address = {Fort Worth,~TX}, 37 | author = {Gaetan K. W. Kenway and Graeme J. Kennedy and Joaquim R. R. A. Martins} 38 | } 39 | ``` 40 | 41 | License 42 | ------- 43 | 44 | Copyright 2019 MDO Lab. See the LICENSE file for details. 45 | 46 | -------------------------------------------------------------------------------- /Rules.mk: -------------------------------------------------------------------------------- 1 | %.o: %.F90 2 | $(FF90) $(FF90_ALL_FLAGS) -c $< -o $(OBJDIR)/$(@F) 3 | @echo 4 | @echo " --- Compiled $*.F90 successfully ---" 5 | @echo 6 | 7 | %.o: %.f90 8 | $(FF90) $(FF90_ALL_FLAGS) -c $< -o $(OBJDIR)/$(@F) 9 | @echo 10 | @echo " --- Compiled $*.f90 successfully ---" 11 | @echo 12 | 13 | %.o: %.f 14 | $(FF90) $(FF90_ALL_FLAGS) -c $< -o $(OBJDIR)/$(@F) 15 | @echo 16 | @echo " --- Compiled $*.f successfully ---" 17 | @echo 18 | 19 | %.o: %.c 20 | $(CC) $(CC_ALL_FLAGS) -c $< -o $(OBJDIR)/$(@F) 21 | @echo 22 | @echo " --- Compiled $*.c successfully ---" 23 | @echo 24 | 25 | -------------------------------------------------------------------------------- /config/defaults/config.LINUX_GFORTRAN.mk: -------------------------------------------------------------------------------- 1 | # Config File for LINUX and GFORTRAN Compiler 2 | AR = ar 3 | AR_FLAGS = -rvs 4 | RM = /bin/rm -rf 5 | 6 | # Fortran compiler and flags 7 | FF90 = gfortran 8 | FF90_FLAGS = -fdefault-real-8 -O2 -fPIC -std=f2008 9 | 10 | # C compiler and flags 11 | CC = gcc 12 | CC_FLAGS = -O2 -fPIC -std=c99 13 | 14 | # Define potentially different python, python-config and f2py executables: 15 | PYTHON = python 16 | PYTHON-CONFIG = python3-config # use python-config for python 2 17 | F2PY = f2py 18 | 19 | # Define additional flags for linking 20 | LINKER_FLAGS = 21 | SO_LINKER_FLAGS =-fPIC -shared 22 | -------------------------------------------------------------------------------- /config/defaults/config.LINUX_INTEL.mk: -------------------------------------------------------------------------------- 1 | # Config File for LINUX and INTEL Compiler 2 | AR = ar 3 | AR_FLAGS = -rvs 4 | RM = /bin/rm -rf 5 | 6 | # Note that ";" is there to avoid make shell optimization, otherwise the shell command may fail 7 | ICC_EXISTS := $(shell command -v icc;) 8 | 9 | ifdef ICC_EXISTS 10 | # icc only exists on older Intel versions 11 | # Assume that we want to use the old compilers 12 | FF90 = ifort 13 | CC = icc 14 | else 15 | # Use the new compilers 16 | FF90 = ifx 17 | CC = icx 18 | endif 19 | 20 | # Compiler and flags 21 | FF90_FLAGS = -r8 -O2 -fPIC -stand f08 22 | CC_FLAGS = -O2 -fPIC -std=c99 23 | 24 | # Define potentially different python, python-config and f2py executables: 25 | PYTHON = python 26 | PYTHON-CONFIG = python3-config # use python-config for python 2 27 | F2PY = f2py 28 | 29 | # Define additional flags for linking 30 | LINKER_FLAGS = 31 | SO_LINKER_FLAGS =-fPIC -shared 32 | -------------------------------------------------------------------------------- /config/defaults/config.OSX_GFORTRAN.mk: -------------------------------------------------------------------------------- 1 | # Config File for LINUX and GFORTRAN Compiler 2 | AR = ar 3 | AR_FLAGS = -rvs 4 | RM = /bin/rm -rf 5 | 6 | # Fortran compiler and flags 7 | FF90 = gfortran 8 | FF90_FLAGS = -fdefault-real-8 -O2 -fPIC 9 | 10 | # C compiler and flags 11 | CC = gcc 12 | CC_FLAGS = -O2 -fPIC -std=c99 13 | 14 | # Define potentially different python, python-config and f2py executables: 15 | PYTHON = python 16 | PYTHON-CONFIG = python3-config # use python-config for python 2 17 | F2PY = f2py 18 | 19 | # Define additional flags for linking 20 | LINKER_FLAGS = 21 | SO_LINKER_FLAGS=-fPIC -dynamiclib -single_module -undefined dynamic_lookup -multiply_defined suppress 22 | -------------------------------------------------------------------------------- /doc/API/curve.rst: -------------------------------------------------------------------------------- 1 | Curve 2 | ===== 3 | 4 | .. autoclass:: pyspline.pyCurve.Curve 5 | :members: 6 | -------------------------------------------------------------------------------- /doc/API/surface.rst: -------------------------------------------------------------------------------- 1 | Surface 2 | ------- 3 | 4 | .. autoclass:: pyspline.pySurface.Surface 5 | :members: 6 | -------------------------------------------------------------------------------- /doc/API/utils.rst: -------------------------------------------------------------------------------- 1 | Utils 2 | ----- 3 | 4 | .. automodule:: pyspline.utils 5 | :members: 6 | -------------------------------------------------------------------------------- /doc/API/volume.rst: -------------------------------------------------------------------------------- 1 | Volume 2 | ------ 3 | 4 | .. autoclass:: pyspline.pyVolume.Volume 5 | :members: 6 | -------------------------------------------------------------------------------- /doc/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for Sphinx documentation 2 | # 3 | 4 | # You can set these variables from the command line. 5 | SPHINXOPTS = 6 | SPHINXBUILD = sphinx-build 7 | PAPER = 8 | BUILDDIR = _build 9 | 10 | # Internal variables. 11 | PAPEROPT_a4 = -D latex_paper_size=a4 12 | PAPEROPT_letter = -D latex_paper_size=letter 13 | ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 14 | # the i18n builder cannot share the environment and doctrees with the others 15 | I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . 16 | 17 | .PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext 18 | 19 | help: 20 | @echo "Please use \`make ' where is one of" 21 | @echo " html to make standalone HTML files" 22 | @echo " dirhtml to make HTML files named index.html in directories" 23 | @echo " singlehtml to make a single large HTML file" 24 | @echo " pickle to make pickle files" 25 | @echo " json to make JSON files" 26 | @echo " htmlhelp to make HTML files and a HTML help project" 27 | @echo " qthelp to make HTML files and a qthelp project" 28 | @echo " devhelp to make HTML files and a Devhelp project" 29 | @echo " epub to make an epub" 30 | @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" 31 | @echo " latexpdf to make LaTeX files and run them through pdflatex" 32 | @echo " text to make text files" 33 | @echo " man to make manual pages" 34 | @echo " texinfo to make Texinfo files" 35 | @echo " info to make Texinfo files and run them through makeinfo" 36 | @echo " gettext to make PO message catalogs" 37 | @echo " changes to make an overview of all changed/added/deprecated items" 38 | @echo " linkcheck to check all external links for integrity" 39 | @echo " doctest to run all doctests embedded in the documentation (if enabled)" 40 | 41 | clean: 42 | -rm -rf $(BUILDDIR)/* 43 | 44 | html: 45 | $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html 46 | @echo 47 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." 48 | 49 | dirhtml: 50 | $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml 51 | @echo 52 | @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." 53 | 54 | singlehtml: 55 | $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml 56 | @echo 57 | @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." 58 | 59 | pickle: 60 | $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle 61 | @echo 62 | @echo "Build finished; now you can process the pickle files." 63 | 64 | json: 65 | $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json 66 | @echo 67 | @echo "Build finished; now you can process the JSON files." 68 | 69 | htmlhelp: 70 | $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp 71 | @echo 72 | @echo "Build finished; now you can run HTML Help Workshop with the" \ 73 | ".hhp project file in $(BUILDDIR)/htmlhelp." 74 | 75 | qthelp: 76 | $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp 77 | @echo 78 | @echo "Build finished; now you can run "qcollectiongenerator" with the" \ 79 | ".qhcp project file in $(BUILDDIR)/qthelp, like this:" 80 | @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pySpline.qhcp" 81 | @echo "To view the help file:" 82 | @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pySpline.qhc" 83 | 84 | devhelp: 85 | $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp 86 | @echo 87 | @echo "Build finished." 88 | @echo "To view the help file:" 89 | @echo "# mkdir -p $$HOME/.local/share/devhelp/pySpline" 90 | @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pySpline" 91 | @echo "# devhelp" 92 | 93 | epub: 94 | $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub 95 | @echo 96 | @echo "Build finished. The epub file is in $(BUILDDIR)/epub." 97 | 98 | latex: 99 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 100 | @echo 101 | @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." 102 | @echo "Run \`make' in that directory to run these through (pdf)latex" \ 103 | "(use \`make latexpdf' here to do that automatically)." 104 | 105 | latexpdf: 106 | $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex 107 | @echo "Running LaTeX files through pdflatex..." 108 | $(MAKE) -C $(BUILDDIR)/latex all-pdf 109 | @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." 110 | 111 | text: 112 | $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text 113 | @echo 114 | @echo "Build finished. The text files are in $(BUILDDIR)/text." 115 | 116 | man: 117 | $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man 118 | @echo 119 | @echo "Build finished. The manual pages are in $(BUILDDIR)/man." 120 | 121 | texinfo: 122 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 123 | @echo 124 | @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." 125 | @echo "Run \`make' in that directory to run these through makeinfo" \ 126 | "(use \`make info' here to do that automatically)." 127 | 128 | info: 129 | $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo 130 | @echo "Running Texinfo files through makeinfo..." 131 | make -C $(BUILDDIR)/texinfo info 132 | @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." 133 | 134 | gettext: 135 | $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale 136 | @echo 137 | @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." 138 | 139 | changes: 140 | $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes 141 | @echo 142 | @echo "The overview file is in $(BUILDDIR)/changes." 143 | 144 | linkcheck: 145 | $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck 146 | @echo 147 | @echo "Link check complete; look for any errors in the above output " \ 148 | "or in $(BUILDDIR)/linkcheck/output.txt." 149 | 150 | doctest: 151 | $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest 152 | @echo "Testing of doctests in the sources finished, look at the " \ 153 | "results in $(BUILDDIR)/doctest/output.txt." 154 | -------------------------------------------------------------------------------- /doc/conf.py: -------------------------------------------------------------------------------- 1 | # Standard Python modules 2 | import os 3 | import sys 4 | 5 | # External modules 6 | from sphinx_mdolab_theme.config import * 7 | 8 | # -- Path setup -------------------------------------------------------------- 9 | # If extensions (or modules to document with autodoc) are in another directory, 10 | # add these directories to sys.path here. If the directory is relative to the 11 | # documentation root, use os.path.abspath to make it absolute, like shown here. 12 | 13 | 14 | sys.path.insert(0, os.path.abspath("../")) 15 | 16 | # -- Project information ----------------------------------------------------- 17 | project = "pySpline" 18 | 19 | # mock import for autodoc 20 | autodoc_mock_imports = ["numpy", "scipy", "pyspline.libspline"] 21 | -------------------------------------------------------------------------------- /doc/example_curve.rst: -------------------------------------------------------------------------------- 1 | Curve example 2 | ------------- 3 | 4 | .. literalinclude:: ../examples/example_curve.py 5 | -------------------------------------------------------------------------------- /doc/example_surface.rst: -------------------------------------------------------------------------------- 1 | Surface example 2 | --------------- 3 | 4 | .. literalinclude:: ../examples/example_surf.py 5 | -------------------------------------------------------------------------------- /doc/example_volume.rst: -------------------------------------------------------------------------------- 1 | Volume example 2 | -------------- 3 | 4 | .. literalinclude:: ../examples/example_volume.py 5 | -------------------------------------------------------------------------------- /doc/examples.rst: -------------------------------------------------------------------------------- 1 | .. _pySpline_examples: 2 | 3 | Examples 4 | -------- 5 | Several examples from the ``python/examples`` directory are included 6 | here for reference. 7 | 8 | 9 | .. toctree:: 10 | :maxdepth: 1 11 | 12 | example_curve 13 | example_surface 14 | example_volume 15 | -------------------------------------------------------------------------------- /doc/index.rst: -------------------------------------------------------------------------------- 1 | .. pySpline documentation master file, created by 2 | sphinx-quickstart on Sat Mar 1 10:52:08 2014. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | .. _pySpline: 7 | 8 | ======== 9 | pySpline 10 | ======== 11 | 12 | ``pySpline`` is a package containing code for working with b-spline :class:`~pyspline.pyCurve.Curve`, :class:`~pyspline.pySurface.Surface`, and :class:`~pyspline.pyVolume.Volume` objects. 13 | The Python interface to all functionality is found in the relevant module. 14 | The documentation for this package is summarized below: 15 | 16 | .. toctree:: 17 | :maxdepth: 1 18 | 19 | install 20 | examples 21 | 22 | .. toctree:: 23 | :caption: API Reference 24 | 25 | API/curve 26 | API/surface 27 | API/volume 28 | API/utils 29 | -------------------------------------------------------------------------------- /doc/install.rst: -------------------------------------------------------------------------------- 1 | .. _pySpline_install: 2 | 3 | Installation 4 | ============ 5 | 6 | Building 7 | -------- 8 | 9 | For speed purposes, pySpline uses a small compiled Fortran library for doing the time consuming computational operations. 10 | It is therefore necessary to build this library before using pySpline. 11 | 12 | pySpline follows the standard MDO Lab build procedure. 13 | To start, find a configuration file close to your current setup in:: 14 | 15 | config/defaults 16 | 17 | and copy it to ``config/config.mk``. For example: 18 | 19 | .. prompt:: bash 20 | 21 | cp config/defaults/config.LINUX_GFORTRAN.mk config/config.mk 22 | 23 | If you are a beginner user installing the packages on a linux desktop, 24 | you should use the ``config.LINUX_GFORTRAN.mk`` versions of the configuration 25 | files. The ``config.LINUX_INTEL.mk`` versions are usually used on clusters. 26 | Once you have copied the config file, compile pySpline by running: 27 | 28 | .. prompt:: bash 29 | 30 | make 31 | 32 | If everything was successful, the following lines will be printed to 33 | the screen (near the end):: 34 | 35 | Testing if module libspline can be imported... 36 | Module libspline was successfully imported. 37 | 38 | If you don't see this, it will be necessary to configure the build manually. 39 | To configure manually, open ``config/config.mk`` and modify options as necessary. 40 | 41 | Lastly, to build and install the Python interface, type: 42 | 43 | .. prompt:: bash 44 | 45 | pip install . 46 | 47 | Verification 48 | ------------ 49 | To verify the library, pySpline contains a set of tests that can be run automatically to ensure it reproduces the expected reference results. 50 | To do so, testing dependencies need to be installed first, by typing: 51 | 52 | .. prompt:: bash 53 | 54 | pip install .[testing] 55 | 56 | Once testing dependencies are installed, then to execute all tests, run the following in the root directory, 57 | 58 | .. prompt:: bash 59 | 60 | testflo . 61 | -------------------------------------------------------------------------------- /doc/make.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | REM Command file for Sphinx documentation 4 | 5 | if "%SPHINXBUILD%" == "" ( 6 | set SPHINXBUILD=sphinx-build 7 | ) 8 | set BUILDDIR=_build 9 | set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . 10 | set I18NSPHINXOPTS=%SPHINXOPTS% . 11 | if NOT "%PAPER%" == "" ( 12 | set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% 13 | set I18NSPHINXOPTS=-D latex_paper_size=%PAPER% %I18NSPHINXOPTS% 14 | ) 15 | 16 | if "%1" == "" goto help 17 | 18 | if "%1" == "help" ( 19 | :help 20 | echo.Please use `make ^` where ^ is one of 21 | echo. html to make standalone HTML files 22 | echo. dirhtml to make HTML files named index.html in directories 23 | echo. singlehtml to make a single large HTML file 24 | echo. pickle to make pickle files 25 | echo. json to make JSON files 26 | echo. htmlhelp to make HTML files and a HTML help project 27 | echo. qthelp to make HTML files and a qthelp project 28 | echo. devhelp to make HTML files and a Devhelp project 29 | echo. epub to make an epub 30 | echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter 31 | echo. text to make text files 32 | echo. man to make manual pages 33 | echo. texinfo to make Texinfo files 34 | echo. gettext to make PO message catalogs 35 | echo. changes to make an overview over all changed/added/deprecated items 36 | echo. linkcheck to check all external links for integrity 37 | echo. doctest to run all doctests embedded in the documentation if enabled 38 | goto end 39 | ) 40 | 41 | if "%1" == "clean" ( 42 | for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i 43 | del /q /s %BUILDDIR%\* 44 | goto end 45 | ) 46 | 47 | if "%1" == "html" ( 48 | %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html 49 | if errorlevel 1 exit /b 1 50 | echo. 51 | echo.Build finished. The HTML pages are in %BUILDDIR%/html. 52 | goto end 53 | ) 54 | 55 | if "%1" == "dirhtml" ( 56 | %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml 57 | if errorlevel 1 exit /b 1 58 | echo. 59 | echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. 60 | goto end 61 | ) 62 | 63 | if "%1" == "singlehtml" ( 64 | %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml 65 | if errorlevel 1 exit /b 1 66 | echo. 67 | echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. 68 | goto end 69 | ) 70 | 71 | if "%1" == "pickle" ( 72 | %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle 73 | if errorlevel 1 exit /b 1 74 | echo. 75 | echo.Build finished; now you can process the pickle files. 76 | goto end 77 | ) 78 | 79 | if "%1" == "json" ( 80 | %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json 81 | if errorlevel 1 exit /b 1 82 | echo. 83 | echo.Build finished; now you can process the JSON files. 84 | goto end 85 | ) 86 | 87 | if "%1" == "htmlhelp" ( 88 | %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp 89 | if errorlevel 1 exit /b 1 90 | echo. 91 | echo.Build finished; now you can run HTML Help Workshop with the ^ 92 | .hhp project file in %BUILDDIR%/htmlhelp. 93 | goto end 94 | ) 95 | 96 | if "%1" == "qthelp" ( 97 | %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp 98 | if errorlevel 1 exit /b 1 99 | echo. 100 | echo.Build finished; now you can run "qcollectiongenerator" with the ^ 101 | .qhcp project file in %BUILDDIR%/qthelp, like this: 102 | echo.^> qcollectiongenerator %BUILDDIR%\qthelp\pySpline.qhcp 103 | echo.To view the help file: 104 | echo.^> assistant -collectionFile %BUILDDIR%\qthelp\pySpline.ghc 105 | goto end 106 | ) 107 | 108 | if "%1" == "devhelp" ( 109 | %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp 110 | if errorlevel 1 exit /b 1 111 | echo. 112 | echo.Build finished. 113 | goto end 114 | ) 115 | 116 | if "%1" == "epub" ( 117 | %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub 118 | if errorlevel 1 exit /b 1 119 | echo. 120 | echo.Build finished. The epub file is in %BUILDDIR%/epub. 121 | goto end 122 | ) 123 | 124 | if "%1" == "latex" ( 125 | %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex 126 | if errorlevel 1 exit /b 1 127 | echo. 128 | echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. 129 | goto end 130 | ) 131 | 132 | if "%1" == "text" ( 133 | %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text 134 | if errorlevel 1 exit /b 1 135 | echo. 136 | echo.Build finished. The text files are in %BUILDDIR%/text. 137 | goto end 138 | ) 139 | 140 | if "%1" == "man" ( 141 | %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man 142 | if errorlevel 1 exit /b 1 143 | echo. 144 | echo.Build finished. The manual pages are in %BUILDDIR%/man. 145 | goto end 146 | ) 147 | 148 | if "%1" == "texinfo" ( 149 | %SPHINXBUILD% -b texinfo %ALLSPHINXOPTS% %BUILDDIR%/texinfo 150 | if errorlevel 1 exit /b 1 151 | echo. 152 | echo.Build finished. The Texinfo files are in %BUILDDIR%/texinfo. 153 | goto end 154 | ) 155 | 156 | if "%1" == "gettext" ( 157 | %SPHINXBUILD% -b gettext %I18NSPHINXOPTS% %BUILDDIR%/locale 158 | if errorlevel 1 exit /b 1 159 | echo. 160 | echo.Build finished. The message catalogs are in %BUILDDIR%/locale. 161 | goto end 162 | ) 163 | 164 | if "%1" == "changes" ( 165 | %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes 166 | if errorlevel 1 exit /b 1 167 | echo. 168 | echo.The overview file is in %BUILDDIR%/changes. 169 | goto end 170 | ) 171 | 172 | if "%1" == "linkcheck" ( 173 | %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck 174 | if errorlevel 1 exit /b 1 175 | echo. 176 | echo.Link check complete; look for any errors in the above output ^ 177 | or in %BUILDDIR%/linkcheck/output.txt. 178 | goto end 179 | ) 180 | 181 | if "%1" == "doctest" ( 182 | %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest 183 | if errorlevel 1 exit /b 1 184 | echo. 185 | echo.Testing of doctests in the sources finished, look at the ^ 186 | results in %BUILDDIR%/doctest/output.txt. 187 | goto end 188 | ) 189 | 190 | :end 191 | -------------------------------------------------------------------------------- /doc/requirements.txt: -------------------------------------------------------------------------------- 1 | sphinx_mdolab_theme 2 | -------------------------------------------------------------------------------- /examples/example_curve.py: -------------------------------------------------------------------------------- 1 | # This is a test script to test the functionality of the 2 | # pySpline curve class 3 | 4 | # External modules 5 | import numpy as np 6 | 7 | # First party modules 8 | from pyspline import Curve 9 | 10 | # Get some Helix-like data 11 | 12 | n = 100 13 | theta = np.linspace(0.0000, 2 * np.pi, n) 14 | x = np.cos(theta) 15 | y = np.sin(theta) 16 | z = np.linspace(0, 1, n) 17 | print("Helix Data") 18 | curve = Curve(x=x, y=y, z=z, k=4, nCtl=16, nIter=100) 19 | curve.writeTecplot("helix.dat") 20 | 21 | # Load naca0012 data 22 | print("Naca 0012 data") 23 | x, y = np.loadtxt("naca0012", unpack=True) 24 | curve = Curve(x=x, y=y, k=4, nCtl=11, nIter=500) 25 | curve.writeTecplot("naca_data.dat") 26 | 27 | # Projection Tests 28 | print("Projection Tests") 29 | x = [0, 2, 3, 5] 30 | y = [-2, 5, 3, 0] 31 | z = [0, 0, 0, 0] 32 | curve1 = Curve(x=x, y=y, z=z, k=4) 33 | curve1.writeTecplot("curve1.dat") 34 | 35 | x = [-2, 5, 2, 1] 36 | y = [5, 1, 4, 2] 37 | z = [3, 0, 1, 4] 38 | curve2 = Curve(x=x, y=y, z=z, k=4) 39 | curve2.writeTecplot("curve2.dat") 40 | 41 | # Get the minimum distance distance between a point and each curve 42 | x0 = [4, 4, 3] 43 | s1, D1 = curve1.projectPoint(x0, s=0.5) 44 | val1 = curve1(s1) # Closest point on curve 45 | s2, D2 = curve2.projectPoint(x0, s=1.0) 46 | val2 = curve2(s2) # Closest point on curve 47 | 48 | # Output the data 49 | f = open("projections.dat", "w") 50 | f.write('VARIABLES = "CoordinateX", "CoordinateY", "CoordinateZ"\n') 51 | f.write("Zone T=curve1_proj I=2 \n") 52 | f.write("DATAPACKING=POINT\n") 53 | f.write("%f %f %f\n" % (x0[0], x0[1], x0[2])) 54 | f.write("%f %f %f\n" % (val1[0], val1[1], val1[2])) 55 | 56 | f.write("Zone T=curve2_proj I=2 \n") 57 | f.write("DATAPACKING=POINT\n") 58 | f.write("%f %f %f\n" % (x0[0], x0[1], x0[2])) 59 | f.write("%f %f %f\n" % (val2[0], val2[1], val2[2])) 60 | 61 | # Get the minimum distance between the two curves 62 | s, t, D = curve1.projectCurve(curve2) 63 | val1 = curve1(s) 64 | val2 = curve2(t) 65 | 66 | f.write("Zone T=curve1_curve2 I=2 \n") 67 | f.write("DATAPACKING=POINT\n") 68 | f.write("%f %f %f\n" % (val1[0], val1[1], val1[2])) 69 | f.write("%f %f %f\n" % (val2[0], val2[1], val2[2])) 70 | -------------------------------------------------------------------------------- /examples/example_surf.py: -------------------------------------------------------------------------------- 1 | # This is a test script to test the functionality of the 2 | # pySpline surface 3 | # External modules 4 | import numpy as np 5 | 6 | # First party modules 7 | from pyspline import Curve, Surface 8 | 9 | # Create a generic surface 10 | nu = 20 11 | nv = 20 12 | u = np.linspace(-4, 4, nu) 13 | v = np.linspace(-4, 4, nv) 14 | [V, U] = np.meshgrid(v, u) 15 | Z = np.cos(U) * np.sin(V) 16 | surf = Surface(x=U, y=V, z=Z, ku=4, kv=4, nCtlu=5, nCtlv=5) 17 | surf.writeTecplot("surface.dat") 18 | 19 | n = 100 20 | theta = np.linspace(0.0000, 2 * np.pi, n) 21 | x = np.cos(theta) - 1 22 | y = np.sin(theta) + 1 23 | z = np.linspace(0, 1, n) + 2 24 | curve = Curve(x=x, y=y, z=z, k=4, nCtl=16, nIter=100) 25 | curve.writeTecplot("helix.dat") 26 | 27 | u, v, s, D = surf.projectCurve(curve, nIter=100, eps=1e-10, u=0.5, v=0.5, s=0.5) 28 | val1 = curve(s) 29 | val2 = surf(u, v) 30 | 31 | print(f"{u=}, {v=}, {s=}, {D=}") 32 | print(val1) 33 | print(val2) 34 | 35 | # Output the data 36 | f = open("surface_projections.dat", "w") 37 | f.write('VARIABLES = "CoordinateX", "CoordinateY", "CoordinateZ"\n') 38 | f.write("Zone T=surf_curve_proj I=2 \n") 39 | f.write("DATAPACKING=POINT\n") 40 | f.write("%f %f %f\n" % (val1[0], val1[1], val1[2])) 41 | f.write("%f %f %f\n" % (val2[0], val2[1], val2[2])) 42 | -------------------------------------------------------------------------------- /examples/example_volume.py: -------------------------------------------------------------------------------- 1 | # This simple script test some of the volume functionality in pySpline 2 | # Standard Python modules 3 | import time 4 | 5 | # External modules 6 | import numpy as np 7 | 8 | # First party modules 9 | from pyspline import Volume 10 | 11 | X = np.zeros((2, 2, 2, 3)) 12 | X[0, 0, 0, :] = [0, 0, 0] 13 | X[1, 0, 0, :] = [1.1, -0.1, -0.1] 14 | X[1, 1, 0, :] = [0.9, 1.05, 0.2] 15 | X[0, 1, 0, :] = [-0.1, 1.1, 0] 16 | 17 | X[0, 0, 1, :] = [-0.1, 0.1, 1.5] 18 | X[1, 0, 1, :] = [1.2, -0.2, 1.8] 19 | X[1, 1, 1, :] = [1.2, 1.0, 2] 20 | X[0, 1, 1, :] = [-0.2, 1.3, 2.1] 21 | 22 | vol = Volume(X=X, ku=2, kv=2, kw=2, nCtlu=2, nCtlv=2, nCtlw=2) 23 | vol.writeTecplot("vol.dat", orig=True) 24 | 25 | # Generate random data 26 | M = 10000 27 | Y = np.zeros((M, 3)) 28 | np.random.seed(123) 29 | for i in range(M): 30 | Y[i, 0] = np.random.random() * 0.5 + 0.25 31 | Y[i, 1] = np.random.random() * 0.5 + 0.25 32 | Y[i, 2] = np.random.random() * 0.5 + 0.25 33 | 34 | 35 | timeA = time.time() 36 | u, v, w, D = vol.projectPoint(Y) 37 | print(f"Time to project {M} points: {time.time() - timeA} seconds") 38 | 39 | # visualize the first 10 points on one volume face 40 | N = 10 41 | coords = vol(u[:N], v[:N], np.ones(N)) 42 | 43 | # Output the data 44 | f = open("volume_projections.dat", "w") 45 | f.write('VARIABLES = "CoordinateX", "CoordinateY", "CoordinateZ"\n') 46 | 47 | # Original points 48 | f.write(f"Zone T=original_points I={N} \n") 49 | f.write("DATAPACKING=POINT\n") 50 | for i in range(N): 51 | f.write(f"{Y[i,0]} {Y[i,1]} {Y[i,2]}\n") 52 | 53 | f.write(f"Zone T=vol_point_proj I={N} \n") 54 | f.write("DATAPACKING=POINT\n") 55 | for i in range(N): 56 | f.write(f"{coords[i,0]} {coords[i,1]} {coords[i,2]}\n") 57 | -------------------------------------------------------------------------------- /examples/naca0012: -------------------------------------------------------------------------------- 1 | 1.000000 0.1260000E-02 2 | 0.9937200 0.2137733E-02 3 | 0.9827658 0.3652628E-02 4 | 0.9699775 0.5395763E-02 5 | 0.9556484 0.7317189E-02 6 | 0.9402486 0.9345839E-02 7 | 0.9242123 0.1141940E-01 8 | 0.9078338 0.1349729E-01 9 | 0.8912799 0.1555747E-01 10 | 0.8746367 0.1758921E-01 11 | 0.8579464 0.1958767E-01 12 | 0.8412299 0.2155079E-01 13 | 0.8244974 0.2347775E-01 14 | 0.8077546 0.2536826E-01 15 | 0.7910046 0.2722215E-01 16 | 0.7742495 0.2903929E-01 17 | 0.7574910 0.3081946E-01 18 | 0.7407304 0.3256231E-01 19 | 0.7239692 0.3426741E-01 20 | 0.7072086 0.3593415E-01 21 | 0.6904498 0.3756179E-01 22 | 0.6736942 0.3914944E-01 23 | 0.6569430 0.4069607E-01 24 | 0.6401976 0.4220048E-01 25 | 0.6234593 0.4366132E-01 26 | 0.6067296 0.4507707E-01 27 | 0.5900098 0.4644604E-01 28 | 0.5733015 0.4776639E-01 29 | 0.5566061 0.4903607E-01 30 | 0.5399254 0.5025287E-01 31 | 0.5232609 0.5141440E-01 32 | 0.5066145 0.5251805E-01 33 | 0.4899881 0.5356103E-01 34 | 0.4733836 0.5454034E-01 35 | 0.4568033 0.5545275E-01 36 | 0.4402494 0.5629481E-01 37 | 0.4237245 0.5706282E-01 38 | 0.4072312 0.5775284E-01 39 | 0.3907728 0.5836065E-01 40 | 0.3743523 0.5888176E-01 41 | 0.3579737 0.5931135E-01 42 | 0.3416411 0.5964430E-01 43 | 0.3253592 0.5987512E-01 44 | 0.3091334 0.5999796E-01 45 | 0.2929700 0.6000654E-01 46 | 0.2768762 0.5989415E-01 47 | 0.2608607 0.5965360E-01 48 | 0.2449337 0.5927721E-01 49 | 0.2291078 0.5875675E-01 50 | 0.2133984 0.5808348E-01 51 | 0.1978253 0.5724818E-01 52 | 0.1824140 0.5624130E-01 53 | 0.1671985 0.5505334E-01 54 | 0.1522253 0.5367551E-01 55 | 0.1375585 0.5210105E-01 56 | 0.1232868 0.5032750E-01 57 | 0.1095300 0.4836006E-01 58 | 0.9644040E-01 0.4621587E-01 59 | 0.8419250E-01 0.4392743E-01 60 | 0.7295464E-01 0.4154215E-01 61 | 0.6284856E-01 0.3911578E-01 62 | 0.5391754E-01 0.3670115E-01 63 | 0.4612202E-01 0.3433829E-01 64 | 0.3936201E-01 0.3205037E-01 65 | 0.3350894E-01 0.2984552E-01 66 | 0.2843159E-01 0.2772130E-01 67 | 0.2401083E-01 0.2566907E-01 68 | 0.2014561E-01 0.2367712E-01 69 | 0.1675353E-01 0.2173266E-01 70 | 0.1376927E-01 0.1982291E-01 71 | 0.1114227E-01 0.1793562E-01 72 | 0.8834520E-02 0.1605954E-01 73 | 0.6818652E-02 0.1418471E-01 74 | 0.5076404E-02 0.1230310E-01 75 | 0.3597085E-02 0.1040943E-01 76 | 0.2375947E-02 0.8502398E-02 77 | 0.1411548E-02 0.6585675E-02 78 | 0.7030324E-03 0.4670019E-02 79 | 0.2448913E-03 0.2768967E-02 80 | 0.2616688E-04 0.9084721E-03 81 | 0.2616688E-04 -0.9084721E-03 82 | 0.2448913E-03 -0.2768967E-02 83 | 0.7030324E-03 -0.4670019E-02 84 | 0.1411548E-02 -0.6585675E-02 85 | 0.2375947E-02 -0.8502398E-02 86 | 0.3597085E-02 -0.1040943E-01 87 | 0.5076404E-02 -0.1230310E-01 88 | 0.6818652E-02 -0.1418471E-01 89 | 0.8834520E-02 -0.1605954E-01 90 | 0.1114227E-01 -0.1793562E-01 91 | 0.1376927E-01 -0.1982291E-01 92 | 0.1675353E-01 -0.2173266E-01 93 | 0.2014561E-01 -0.2367712E-01 94 | 0.2401083E-01 -0.2566907E-01 95 | 0.2843159E-01 -0.2772130E-01 96 | 0.3350894E-01 -0.2984552E-01 97 | 0.3936201E-01 -0.3205037E-01 98 | 0.4612202E-01 -0.3433829E-01 99 | 0.5391754E-01 -0.3670115E-01 100 | 0.6284856E-01 -0.3911578E-01 101 | 0.7295464E-01 -0.4154215E-01 102 | 0.8419250E-01 -0.4392743E-01 103 | 0.9644040E-01 -0.4621587E-01 104 | 0.1095300 -0.4836006E-01 105 | 0.1232868 -0.5032750E-01 106 | 0.1375585 -0.5210105E-01 107 | 0.1522253 -0.5367551E-01 108 | 0.1671985 -0.5505334E-01 109 | 0.1824140 -0.5624130E-01 110 | 0.1978253 -0.5724818E-01 111 | 0.2133984 -0.5808348E-01 112 | 0.2291078 -0.5875675E-01 113 | 0.2449337 -0.5927721E-01 114 | 0.2608607 -0.5965360E-01 115 | 0.2768762 -0.5989415E-01 116 | 0.2929700 -0.6000654E-01 117 | 0.3091334 -0.5999796E-01 118 | 0.3253592 -0.5987512E-01 119 | 0.3416411 -0.5964430E-01 120 | 0.3579737 -0.5931135E-01 121 | 0.3743523 -0.5888176E-01 122 | 0.3907728 -0.5836065E-01 123 | 0.4072312 -0.5775284E-01 124 | 0.4237245 -0.5706282E-01 125 | 0.4402494 -0.5629481E-01 126 | 0.4568033 -0.5545275E-01 127 | 0.4733836 -0.5454034E-01 128 | 0.4899881 -0.5356103E-01 129 | 0.5066145 -0.5251805E-01 130 | 0.5232609 -0.5141440E-01 131 | 0.5399254 -0.5025287E-01 132 | 0.5566061 -0.4903607E-01 133 | 0.5733015 -0.4776639E-01 134 | 0.5900098 -0.4644604E-01 135 | 0.6067296 -0.4507707E-01 136 | 0.6234593 -0.4366132E-01 137 | 0.6401976 -0.4220048E-01 138 | 0.6569430 -0.4069607E-01 139 | 0.6736942 -0.3914944E-01 140 | 0.6904498 -0.3756179E-01 141 | 0.7072086 -0.3593415E-01 142 | 0.7239692 -0.3426741E-01 143 | 0.7407304 -0.3256231E-01 144 | 0.7574910 -0.3081946E-01 145 | 0.7742495 -0.2903929E-01 146 | 0.7910046 -0.2722215E-01 147 | 0.8077546 -0.2536826E-01 148 | 0.8244974 -0.2347775E-01 149 | 0.8412299 -0.2155079E-01 150 | 0.8579464 -0.1958767E-01 151 | 0.8746367 -0.1758921E-01 152 | 0.8912799 -0.1555747E-01 153 | 0.9078338 -0.1349729E-01 154 | 0.9242123 -0.1141940E-01 155 | 0.9402486 -0.9345839E-02 156 | 0.9556484 -0.7317189E-02 157 | 0.9699775 -0.5395763E-02 158 | 0.9827658 -0.3652628E-02 159 | 0.9937200 -0.2137733E-02 160 | 1.000000 -0.1260000E-02 161 | -------------------------------------------------------------------------------- /examples/surface.lay: -------------------------------------------------------------------------------- 1 | #!MC 1410 2 | $!VarSet |LFDSFN1| = '"surface.dat"' 3 | $!VarSet |LFDSVL1| = '"CoordinateX" "CoordinateY" "CoordinateZ"' 4 | $!VarSet |LFDSFN2| = '"surface_projections.dat" "helix.dat"' 5 | $!VarSet |LFDSVL2| = '"CoordinateX" "CoordinateY" "CoordinateZ"' 6 | $!SetStyleBase Factory 7 | $!CreateColorMap 8 | Name = 'Sequential - Viridis' 9 | NumControlPoints = 11 10 | ControlPoint 1 11 | { 12 | ColorMapFraction = 0 13 | LeadRGB 14 | { 15 | R = 68 16 | G = 1 17 | B = 84 18 | } 19 | TrailRGB 20 | { 21 | R = 68 22 | G = 1 23 | B = 84 24 | } 25 | } 26 | ControlPoint 2 27 | { 28 | ColorMapFraction = 0.08163 29 | LeadRGB 30 | { 31 | R = 72 32 | G = 31 33 | B = 112 34 | } 35 | TrailRGB 36 | { 37 | R = 72 38 | G = 31 39 | B = 112 40 | } 41 | } 42 | ControlPoint 3 43 | { 44 | ColorMapFraction = 0.1837 45 | LeadRGB 46 | { 47 | R = 67 48 | G = 63 49 | B = 133 50 | } 51 | TrailRGB 52 | { 53 | R = 67 54 | G = 63 55 | B = 133 56 | } 57 | } 58 | ControlPoint 4 59 | { 60 | ColorMapFraction = 0.2857 61 | LeadRGB 62 | { 63 | R = 54 64 | G = 92 65 | B = 141 66 | } 67 | TrailRGB 68 | { 69 | R = 54 70 | G = 92 71 | B = 141 72 | } 73 | } 74 | ControlPoint 5 75 | { 76 | ColorMapFraction = 0.3878 77 | LeadRGB 78 | { 79 | R = 43 80 | G = 117 81 | B = 142 82 | } 83 | TrailRGB 84 | { 85 | R = 43 86 | G = 117 87 | B = 142 88 | } 89 | } 90 | ControlPoint 6 91 | { 92 | ColorMapFraction = 0.4898 93 | LeadRGB 94 | { 95 | R = 33 96 | G = 142 97 | B = 141 98 | } 99 | TrailRGB 100 | { 101 | R = 33 102 | G = 142 103 | B = 141 104 | } 105 | } 106 | ControlPoint 7 107 | { 108 | ColorMapFraction = 0.5918 109 | LeadRGB 110 | { 111 | R = 33 112 | G = 166 113 | B = 133 114 | } 115 | TrailRGB 116 | { 117 | R = 33 118 | G = 166 119 | B = 133 120 | } 121 | } 122 | ControlPoint 8 123 | { 124 | ColorMapFraction = 0.6939 125 | LeadRGB 126 | { 127 | R = 64 128 | G = 189 129 | B = 114 130 | } 131 | TrailRGB 132 | { 133 | R = 64 134 | G = 189 135 | B = 114 136 | } 137 | } 138 | ControlPoint 9 139 | { 140 | ColorMapFraction = 0.7959 141 | LeadRGB 142 | { 143 | R = 119 144 | G = 209 145 | B = 83 146 | } 147 | TrailRGB 148 | { 149 | R = 119 150 | G = 209 151 | B = 83 152 | } 153 | } 154 | ControlPoint 10 155 | { 156 | ColorMapFraction = 0.898 157 | LeadRGB 158 | { 159 | R = 186 160 | G = 222 161 | B = 40 162 | } 163 | TrailRGB 164 | { 165 | R = 186 166 | G = 222 167 | B = 40 168 | } 169 | } 170 | ControlPoint 11 171 | { 172 | ColorMapFraction = 1 173 | LeadRGB 174 | { 175 | R = 253 176 | G = 231 177 | B = 37 178 | } 179 | TrailRGB 180 | { 181 | R = 253 182 | G = 231 183 | B = 37 184 | } 185 | } 186 | $!GlobalPaper 187 | PaperSizeInfo 188 | { 189 | Letter 190 | { 191 | Width = 8.5 192 | Height = 11 193 | LeftHardClipOffset = 0.125 194 | RightHardClipOffset = 0.125 195 | TopHardClipOffset = 0.125 196 | BottomHardClipOffset = 0.125 197 | } 198 | } 199 | $!Page 200 | Name = 'Untitled' 201 | PaperAttributes 202 | { 203 | BackgroundColor = White 204 | IsTransparent = Yes 205 | OrientPortrait = No 206 | ShowGrid = Yes 207 | ShowRuler = No 208 | ShowPaper = No 209 | PaperSize = Letter 210 | RulerSpacing = OneInch 211 | PaperGridSpacing = HalfInch 212 | RegionInWorkArea 213 | { 214 | X1 = 1 215 | Y1 = 0.25 216 | X2 = 10 217 | Y2 = 8.25 218 | } 219 | } 220 | ### Frame Number 1 ### 221 | $!ReadDataSet '|LFDSFN1|' 222 | InitialPlotType = Cartesian3D 223 | IncludeText = No 224 | IncludeGeom = No 225 | AssignStrandIDs = Yes 226 | VarLoadMode = ByName 227 | VarNameList = '|LFDSVL1|' 228 | $!RemoveVar |LFDSVL1| 229 | $!RemoveVar |LFDSFN1| 230 | $!ReadDataSet '|LFDSFN2|' 231 | InitialPlotType = Cartesian3D 232 | IncludeText = No 233 | IncludeGeom = No 234 | ReadDataOption = Append 235 | ResetStyle = No 236 | AssignStrandIDs = Yes 237 | VarLoadMode = ByName 238 | VarNameList = '|LFDSVL2|' 239 | $!RemoveVar |LFDSVL2| 240 | $!RemoveVar |LFDSFN2| 241 | $!FrameLayout 242 | ShowHeader = No 243 | HeaderColor = Red 244 | XYPos 245 | { 246 | X = 1 247 | Y = 0.25 248 | } 249 | Width = 9 250 | Height = 8 251 | $!ThreeDAxis 252 | AspectRatioLimit = 25 253 | BoxAspectRatioLimit = 25 254 | $!PlotType = Cartesian3D 255 | $!FrameName = 'Frame 001' 256 | $!GlobalTime 257 | SolutionTime = 0 258 | $!ActiveFieldMaps = [1,4-5] 259 | $!GlobalRGB 260 | RedChannelVar = 3 261 | GreenChannelVar = 3 262 | BlueChannelVar = 3 263 | RangeMin = 0 264 | RangeMax = 1 265 | $!GlobalContour 1 266 | Var = 3 267 | ColorMapName = 'Sequential - Viridis' 268 | DefNumLevels = 18 269 | Legend 270 | { 271 | Show = Yes 272 | XYPos 273 | { 274 | X = 95 275 | } 276 | } 277 | ColorCutoff 278 | { 279 | RangeMin = -1.17049604802 280 | RangeMax = 0.701439535729 281 | } 282 | ColorMapFilter 283 | { 284 | ContinuousColor 285 | { 286 | CMin = -2.10646383989 287 | CMax = 1.6374073276 288 | } 289 | } 290 | $!ContourLevels New 291 | ContourGroup = 1 292 | RawData 293 | 18 294 | -2 295 | -1.8 296 | -1.6 297 | -1.4 298 | -1.2 299 | -1 300 | -0.8 301 | -0.6 302 | -0.4 303 | -0.2 304 | 0 305 | 0.2 306 | 0.4 307 | 0.6 308 | 0.8 309 | 1 310 | 1.2 311 | 1.4 312 | $!GlobalContour 2 313 | Var = 3 314 | ColorMapName = 'Sequential - Viridis' 315 | DefNumLevels = 19 316 | Legend 317 | { 318 | Show = Yes 319 | XYPos 320 | { 321 | X = 95 322 | } 323 | } 324 | ColorMapFilter 325 | { 326 | ContinuousColor 327 | { 328 | CMin = 0 329 | CMax = 1 330 | } 331 | } 332 | $!ContourLevels New 333 | ContourGroup = 2 334 | RawData 335 | 19 336 | -0.8 337 | -0.6 338 | -0.4 339 | -0.2 340 | 0 341 | 0.2 342 | 0.4 343 | 0.6 344 | 0.8 345 | 1 346 | 1.2 347 | 1.4 348 | 1.6 349 | 1.8 350 | 2 351 | 2.2 352 | 2.4 353 | 2.6 354 | 2.8 355 | $!GlobalContour 3 356 | Var = 3 357 | ColorMapName = 'Sequential - Viridis' 358 | DefNumLevels = 19 359 | Legend 360 | { 361 | Show = Yes 362 | XYPos 363 | { 364 | X = 95 365 | } 366 | } 367 | ColorMapFilter 368 | { 369 | ContinuousColor 370 | { 371 | CMin = 0 372 | CMax = 1 373 | } 374 | } 375 | $!ContourLevels New 376 | ContourGroup = 3 377 | RawData 378 | 19 379 | -0.8 380 | -0.6 381 | -0.4 382 | -0.2 383 | 0 384 | 0.2 385 | 0.4 386 | 0.6 387 | 0.8 388 | 1 389 | 1.2 390 | 1.4 391 | 1.6 392 | 1.8 393 | 2 394 | 2.2 395 | 2.4 396 | 2.6 397 | 2.8 398 | $!GlobalContour 4 399 | Var = 3 400 | ColorMapName = 'Sequential - Viridis' 401 | DefNumLevels = 19 402 | Legend 403 | { 404 | Show = Yes 405 | XYPos 406 | { 407 | X = 95 408 | } 409 | } 410 | ColorMapFilter 411 | { 412 | ContinuousColor 413 | { 414 | CMin = 0 415 | CMax = 1 416 | } 417 | } 418 | $!ContourLevels New 419 | ContourGroup = 4 420 | RawData 421 | 19 422 | -0.8 423 | -0.6 424 | -0.4 425 | -0.2 426 | 0 427 | 0.2 428 | 0.4 429 | 0.6 430 | 0.8 431 | 1 432 | 1.2 433 | 1.4 434 | 1.6 435 | 1.8 436 | 2 437 | 2.2 438 | 2.4 439 | 2.6 440 | 2.8 441 | $!GlobalContour 5 442 | Var = 3 443 | ColorMapName = 'Sequential - Viridis' 444 | DefNumLevels = 19 445 | Legend 446 | { 447 | Show = Yes 448 | XYPos 449 | { 450 | X = 95 451 | } 452 | } 453 | ColorMapFilter 454 | { 455 | ContinuousColor 456 | { 457 | CMin = 0 458 | CMax = 1 459 | } 460 | } 461 | $!ContourLevels New 462 | ContourGroup = 5 463 | RawData 464 | 19 465 | -0.8 466 | -0.6 467 | -0.4 468 | -0.2 469 | 0 470 | 0.2 471 | 0.4 472 | 0.6 473 | 0.8 474 | 1 475 | 1.2 476 | 1.4 477 | 1.6 478 | 1.8 479 | 2 480 | 2.2 481 | 2.4 482 | 2.6 483 | 2.8 484 | $!GlobalContour 6 485 | Var = 3 486 | ColorMapName = 'Sequential - Viridis' 487 | DefNumLevels = 19 488 | Legend 489 | { 490 | Show = Yes 491 | XYPos 492 | { 493 | X = 95 494 | } 495 | } 496 | ColorMapFilter 497 | { 498 | ContinuousColor 499 | { 500 | CMin = 0 501 | CMax = 1 502 | } 503 | } 504 | $!ContourLevels New 505 | ContourGroup = 6 506 | RawData 507 | 19 508 | -0.8 509 | -0.6 510 | -0.4 511 | -0.2 512 | 0 513 | 0.2 514 | 0.4 515 | 0.6 516 | 0.8 517 | 1 518 | 1.2 519 | 1.4 520 | 1.6 521 | 1.8 522 | 2 523 | 2.2 524 | 2.4 525 | 2.6 526 | 2.8 527 | $!GlobalContour 7 528 | Var = 3 529 | ColorMapName = 'Sequential - Viridis' 530 | DefNumLevels = 19 531 | Legend 532 | { 533 | Show = Yes 534 | XYPos 535 | { 536 | X = 95 537 | } 538 | } 539 | ColorMapFilter 540 | { 541 | ContinuousColor 542 | { 543 | CMin = 0 544 | CMax = 1 545 | } 546 | } 547 | $!ContourLevels New 548 | ContourGroup = 7 549 | RawData 550 | 19 551 | -0.8 552 | -0.6 553 | -0.4 554 | -0.2 555 | 0 556 | 0.2 557 | 0.4 558 | 0.6 559 | 0.8 560 | 1 561 | 1.2 562 | 1.4 563 | 1.6 564 | 1.8 565 | 2 566 | 2.2 567 | 2.4 568 | 2.6 569 | 2.8 570 | $!GlobalContour 8 571 | Var = 3 572 | ColorMapName = 'Sequential - Viridis' 573 | DefNumLevels = 19 574 | Legend 575 | { 576 | Show = Yes 577 | XYPos 578 | { 579 | X = 95 580 | } 581 | } 582 | ColorMapFilter 583 | { 584 | ContinuousColor 585 | { 586 | CMin = 0 587 | CMax = 1 588 | } 589 | } 590 | $!ContourLevels New 591 | ContourGroup = 8 592 | RawData 593 | 19 594 | -0.8 595 | -0.6 596 | -0.4 597 | -0.2 598 | 0 599 | 0.2 600 | 0.4 601 | 0.6 602 | 0.8 603 | 1 604 | 1.2 605 | 1.4 606 | 1.6 607 | 1.8 608 | 2 609 | 2.2 610 | 2.4 611 | 2.6 612 | 2.8 613 | $!GlobalScatter 614 | Var = 3 615 | RelativeSize = 0.05005 616 | Legend 617 | { 618 | XYPos 619 | { 620 | X = 95 621 | } 622 | } 623 | RefScatSymbol 624 | { 625 | Color = Red 626 | FillColor = Red 627 | } 628 | $!FieldMap [1-3] 629 | Mesh 630 | { 631 | Color = Black 632 | } 633 | Contour 634 | { 635 | ContourType = Flood 636 | Color = Black 637 | UseLightingEffect = Yes 638 | } 639 | Vector 640 | { 641 | Color = Black 642 | } 643 | Scatter 644 | { 645 | Show = No 646 | Color = Black 647 | } 648 | Shade 649 | { 650 | Color = Custom2 651 | } 652 | EdgeLayer 653 | { 654 | Show = Yes 655 | Color = Black 656 | LineThickness = 0.1 657 | } 658 | Points 659 | { 660 | PointsToPlot = SurfaceNodes 661 | } 662 | Surfaces 663 | { 664 | SurfacesToPlot = KPlanes 665 | IRange 666 | { 667 | Max = 1 668 | } 669 | } 670 | VolumeMode 671 | { 672 | VolumeObjectsToPlot 673 | { 674 | ShowIsosurfaces = No 675 | ShowSlices = No 676 | ShowStreamtraces = No 677 | } 678 | } 679 | Effects 680 | { 681 | LightingEffect = Gouraud 682 | } 683 | $!FieldMap [4] 684 | Mesh 685 | { 686 | Color = Black 687 | } 688 | Contour 689 | { 690 | ContourType = Flood 691 | Color = Black 692 | UseLightingEffect = Yes 693 | } 694 | Vector 695 | { 696 | Color = Black 697 | } 698 | Scatter 699 | { 700 | SymbolShape 701 | { 702 | GeomShape = Cube 703 | } 704 | Color = Black 705 | } 706 | Shade 707 | { 708 | Color = Custom2 709 | } 710 | EdgeLayer 711 | { 712 | Show = No 713 | Color = Black 714 | LineThickness = 0.1 715 | } 716 | Points 717 | { 718 | PointsToPlot = SurfaceNodes 719 | } 720 | Surfaces 721 | { 722 | SurfacesToPlot = KPlanes 723 | IRange 724 | { 725 | Max = 1 726 | } 727 | } 728 | VolumeMode 729 | { 730 | VolumeObjectsToPlot 731 | { 732 | ShowIsosurfaces = No 733 | ShowSlices = No 734 | ShowStreamtraces = No 735 | } 736 | } 737 | Effects 738 | { 739 | LightingEffect = Gouraud 740 | } 741 | $!FieldMap [5] 742 | Mesh 743 | { 744 | Color = Red 745 | } 746 | Contour 747 | { 748 | ContourType = Flood 749 | Color = Black 750 | UseLightingEffect = Yes 751 | } 752 | Vector 753 | { 754 | Color = Black 755 | } 756 | Scatter 757 | { 758 | Show = No 759 | Color = Black 760 | } 761 | Shade 762 | { 763 | Color = Custom2 764 | } 765 | EdgeLayer 766 | { 767 | Show = No 768 | Color = Black 769 | LineThickness = 0.1 770 | } 771 | Points 772 | { 773 | PointsToPlot = SurfaceNodes 774 | } 775 | Surfaces 776 | { 777 | SurfacesToPlot = KPlanes 778 | IRange 779 | { 780 | Max = 1 781 | } 782 | } 783 | VolumeMode 784 | { 785 | VolumeObjectsToPlot 786 | { 787 | ShowIsosurfaces = No 788 | ShowSlices = No 789 | ShowStreamtraces = No 790 | } 791 | } 792 | Effects 793 | { 794 | LightingEffect = Gouraud 795 | } 796 | $!FieldMap [6-7] 797 | Mesh 798 | { 799 | Color = Black 800 | } 801 | Contour 802 | { 803 | ContourType = Flood 804 | Color = Black 805 | UseLightingEffect = Yes 806 | } 807 | Vector 808 | { 809 | Color = Black 810 | } 811 | Scatter 812 | { 813 | Show = No 814 | Color = Black 815 | } 816 | Shade 817 | { 818 | Color = Custom2 819 | } 820 | EdgeLayer 821 | { 822 | Show = No 823 | Color = Black 824 | LineThickness = 0.1 825 | } 826 | Points 827 | { 828 | PointsToPlot = SurfaceNodes 829 | } 830 | Surfaces 831 | { 832 | SurfacesToPlot = KPlanes 833 | IRange 834 | { 835 | Max = 1 836 | } 837 | } 838 | VolumeMode 839 | { 840 | VolumeObjectsToPlot 841 | { 842 | ShowIsosurfaces = No 843 | ShowSlices = No 844 | ShowStreamtraces = No 845 | } 846 | } 847 | Effects 848 | { 849 | LightingEffect = Gouraud 850 | } 851 | $!ThreeDAxis 852 | XDetail 853 | { 854 | VarNum = 1 855 | } 856 | YDetail 857 | { 858 | VarNum = 2 859 | } 860 | ZDetail 861 | { 862 | VarNum = 3 863 | } 864 | $!View Fit 865 | $!ThreeDAxis 866 | AxisMode = XYZDependent 867 | XYDepXToYRatio = 1 868 | DepXToYRatio = 1 869 | DepXToZRatio = 1 870 | $!ThreeDAxis 871 | XDetail 872 | { 873 | ShowAxis = No 874 | RangeMin = -0.22656726992967307632 875 | RangeMax = 4.2375725432965705153 876 | GRSpacing = 1 877 | AxisLine 878 | { 879 | Edge = 2 880 | } 881 | } 882 | $!ThreeDAxis 883 | YDetail 884 | { 885 | ShowAxis = No 886 | RangeMin = -0.224032422745455706 887 | RangeMax = 4.204681212800047696 888 | GRSpacing = 1 889 | AxisLine 890 | { 891 | Edge = 3 892 | } 893 | } 894 | $!ThreeDAxis 895 | ZDetail 896 | { 897 | ShowAxis = No 898 | RangeMin = -2.2936573982634067548 899 | RangeMax = 1.8246008859758298115 900 | GRSpacing = 1 901 | AxisLine 902 | { 903 | Edge = 2 904 | } 905 | } 906 | $!IsoSurfaceAttributes 1 907 | IsoSurfaceSelection = OneSpecificValue 908 | Isovalue1 = -1.17049604802 909 | Isovalue2 = -0.234528256144 910 | Isovalue3 = 0.701439535729 911 | Effects 912 | { 913 | LightingEffect = Gouraud 914 | } 915 | $!IsoSurfaceAttributes 2 916 | DefinitionContourGroup = 2 917 | IsoSurfaceSelection = OneSpecificValue 918 | Contour 919 | { 920 | LineContourGroup = 2 921 | FloodColoring = Group2 922 | } 923 | Effects 924 | { 925 | LightingEffect = Gouraud 926 | } 927 | $!IsoSurfaceAttributes 3 928 | DefinitionContourGroup = 3 929 | IsoSurfaceSelection = OneSpecificValue 930 | Contour 931 | { 932 | LineContourGroup = 3 933 | FloodColoring = Group3 934 | } 935 | Effects 936 | { 937 | LightingEffect = Gouraud 938 | } 939 | $!IsoSurfaceAttributes 4 940 | DefinitionContourGroup = 4 941 | IsoSurfaceSelection = OneSpecificValue 942 | Contour 943 | { 944 | LineContourGroup = 4 945 | FloodColoring = Group4 946 | } 947 | Effects 948 | { 949 | LightingEffect = Gouraud 950 | } 951 | $!IsoSurfaceAttributes 5 952 | DefinitionContourGroup = 5 953 | IsoSurfaceSelection = OneSpecificValue 954 | Contour 955 | { 956 | LineContourGroup = 5 957 | FloodColoring = Group5 958 | } 959 | Effects 960 | { 961 | LightingEffect = Gouraud 962 | } 963 | $!IsoSurfaceAttributes 6 964 | DefinitionContourGroup = 6 965 | IsoSurfaceSelection = OneSpecificValue 966 | Contour 967 | { 968 | LineContourGroup = 6 969 | FloodColoring = Group6 970 | } 971 | Effects 972 | { 973 | LightingEffect = Gouraud 974 | } 975 | $!IsoSurfaceAttributes 7 976 | DefinitionContourGroup = 7 977 | IsoSurfaceSelection = OneSpecificValue 978 | Contour 979 | { 980 | LineContourGroup = 7 981 | FloodColoring = Group7 982 | } 983 | Effects 984 | { 985 | LightingEffect = Gouraud 986 | } 987 | $!IsoSurfaceAttributes 8 988 | DefinitionContourGroup = 8 989 | IsoSurfaceSelection = OneSpecificValue 990 | Contour 991 | { 992 | LineContourGroup = 8 993 | FloodColoring = Group8 994 | } 995 | Effects 996 | { 997 | LightingEffect = Gouraud 998 | } 999 | $!SliceAttributes 1 1000 | PrimaryPosition 1001 | { 1002 | X = 0 1003 | Y = 0 1004 | Z = 0 1005 | I = 1 1006 | J = 1 1007 | K = 1 1008 | } 1009 | StartPosition 1010 | { 1011 | X = -3.6 1012 | Y = -3.6 1013 | Z = -0.795398269472 1014 | } 1015 | EndPosition 1016 | { 1017 | X = 3.6 1018 | Y = 3.6 1019 | Z = 2.80024219634 1020 | } 1021 | EdgeLayer 1022 | { 1023 | Show = No 1024 | } 1025 | Effects 1026 | { 1027 | LightingEffect = Gouraud 1028 | SurfaceTranslucency = 10 1029 | } 1030 | SliceConstraint 1031 | { 1032 | Include = No 1033 | Origin 1034 | { 1035 | X = 0 1036 | Y = 0 1037 | Z = 0 1038 | } 1039 | BoxDimension 1040 | { 1041 | X = 0 1042 | Y = 0 1043 | Z = 0 1044 | } 1045 | } 1046 | $!SliceAttributes 2 1047 | SliceSurface = YPlanes 1048 | EdgeLayer 1049 | { 1050 | Show = No 1051 | } 1052 | Effects 1053 | { 1054 | LightingEffect = Gouraud 1055 | SurfaceTranslucency = 10 1056 | } 1057 | $!SliceAttributes 3 1058 | SliceSurface = ZPlanes 1059 | EdgeLayer 1060 | { 1061 | Show = No 1062 | } 1063 | Effects 1064 | { 1065 | LightingEffect = Gouraud 1066 | SurfaceTranslucency = 10 1067 | } 1068 | $!SliceAttributes 4 1069 | EdgeLayer 1070 | { 1071 | Show = No 1072 | } 1073 | Effects 1074 | { 1075 | LightingEffect = Gouraud 1076 | SurfaceTranslucency = 10 1077 | } 1078 | $!SliceAttributes 5 1079 | SliceSurface = YPlanes 1080 | EdgeLayer 1081 | { 1082 | Show = No 1083 | } 1084 | Effects 1085 | { 1086 | LightingEffect = Gouraud 1087 | SurfaceTranslucency = 10 1088 | } 1089 | $!SliceAttributes 6 1090 | SliceSurface = ZPlanes 1091 | EdgeLayer 1092 | { 1093 | Show = No 1094 | } 1095 | Effects 1096 | { 1097 | LightingEffect = Gouraud 1098 | SurfaceTranslucency = 10 1099 | } 1100 | $!SliceAttributes 7 1101 | EdgeLayer 1102 | { 1103 | Show = No 1104 | } 1105 | Effects 1106 | { 1107 | LightingEffect = Gouraud 1108 | SurfaceTranslucency = 10 1109 | } 1110 | $!SliceAttributes 8 1111 | SliceSurface = YPlanes 1112 | EdgeLayer 1113 | { 1114 | Show = No 1115 | } 1116 | Effects 1117 | { 1118 | LightingEffect = Gouraud 1119 | SurfaceTranslucency = 10 1120 | } 1121 | $!StreamAttributes 1122 | StreamTiming 1123 | { 1124 | MarkSize = 1 1125 | MarkSymbol 1126 | { 1127 | GeomShape = Sphere 1128 | } 1129 | } 1130 | RodRibbon 1131 | { 1132 | Effects 1133 | { 1134 | LightingEffect = Gouraud 1135 | } 1136 | } 1137 | MaxSteps = 10000 1138 | $!GlobalThreeD 1139 | AxisScaleFact 1140 | { 1141 | X = 1 1142 | Y = 1 1143 | Z = 1 1144 | } 1145 | RotateOrigin 1146 | { 1147 | X = 2.005502636683449 1148 | Y = 1.990324395027296 1149 | Z = -0.2345282561437885 1150 | } 1151 | LightSource 1152 | { 1153 | XYZDirection 1154 | { 1155 | X = -0.2 1156 | Y = -0.2 1157 | Z = 0.9591663046625438 1158 | } 1159 | Intensity = 75 1160 | BackgroundLight = 25 1161 | IncludeSpecular = Yes 1162 | SpecularIntensity = 40 1163 | SpecularShininess = 60 1164 | } 1165 | LineLiftFraction = 0.2 1166 | SymbolLiftFraction = 0.6 1167 | VectorLiftFraction = 0.7 1168 | NearPlaneFraction = 0.1 1169 | $!ThreeDView 1170 | PSIAngle = 51.4769 1171 | ThetaAngle = -125.923 1172 | AlphaAngle = 4.29534 1173 | ViewerPosition 1174 | { 1175 | X = 25.8952931536309 1176 | Y = 19.90608709401953 1177 | Z = 26.4101616254007 1178 | } 1179 | ViewWidth = 11.1796 1180 | $!FieldLayers 1181 | ShowContour = Yes 1182 | ShowScatter = Yes 1183 | ShowShade = Yes 1184 | ShowEdge = No 1185 | $!StreamtraceLayers 1186 | Show = No 1187 | $!FrameControl ActivateByNumber 1188 | Frame = 1 1189 | $!SetStyleBase Config 1190 | -------------------------------------------------------------------------------- /examples/volume.lay: -------------------------------------------------------------------------------- 1 | #!MC 1410 2 | $!VarSet |LFDSFN1| = '"vol.dat"' 3 | $!VarSet |LFDSVL1| = '"CoordinateX" "CoordinateY" "CoordinateZ"' 4 | $!VarSet |LFDSFN2| = '"volume_projections.dat"' 5 | $!VarSet |LFDSVL2| = '"CoordinateX" "CoordinateY" "CoordinateZ"' 6 | $!SetStyleBase Factory 7 | $!CreateColorMap 8 | Name = 'Sequential - Viridis' 9 | NumControlPoints = 11 10 | ControlPoint 1 11 | { 12 | ColorMapFraction = 0 13 | LeadRGB 14 | { 15 | R = 68 16 | G = 1 17 | B = 84 18 | } 19 | TrailRGB 20 | { 21 | R = 68 22 | G = 1 23 | B = 84 24 | } 25 | } 26 | ControlPoint 2 27 | { 28 | ColorMapFraction = 0.08163 29 | LeadRGB 30 | { 31 | R = 72 32 | G = 31 33 | B = 112 34 | } 35 | TrailRGB 36 | { 37 | R = 72 38 | G = 31 39 | B = 112 40 | } 41 | } 42 | ControlPoint 3 43 | { 44 | ColorMapFraction = 0.1837 45 | LeadRGB 46 | { 47 | R = 67 48 | G = 63 49 | B = 133 50 | } 51 | TrailRGB 52 | { 53 | R = 67 54 | G = 63 55 | B = 133 56 | } 57 | } 58 | ControlPoint 4 59 | { 60 | ColorMapFraction = 0.2857 61 | LeadRGB 62 | { 63 | R = 54 64 | G = 92 65 | B = 141 66 | } 67 | TrailRGB 68 | { 69 | R = 54 70 | G = 92 71 | B = 141 72 | } 73 | } 74 | ControlPoint 5 75 | { 76 | ColorMapFraction = 0.3878 77 | LeadRGB 78 | { 79 | R = 43 80 | G = 117 81 | B = 142 82 | } 83 | TrailRGB 84 | { 85 | R = 43 86 | G = 117 87 | B = 142 88 | } 89 | } 90 | ControlPoint 6 91 | { 92 | ColorMapFraction = 0.4898 93 | LeadRGB 94 | { 95 | R = 33 96 | G = 142 97 | B = 141 98 | } 99 | TrailRGB 100 | { 101 | R = 33 102 | G = 142 103 | B = 141 104 | } 105 | } 106 | ControlPoint 7 107 | { 108 | ColorMapFraction = 0.5918 109 | LeadRGB 110 | { 111 | R = 33 112 | G = 166 113 | B = 133 114 | } 115 | TrailRGB 116 | { 117 | R = 33 118 | G = 166 119 | B = 133 120 | } 121 | } 122 | ControlPoint 8 123 | { 124 | ColorMapFraction = 0.6939 125 | LeadRGB 126 | { 127 | R = 64 128 | G = 189 129 | B = 114 130 | } 131 | TrailRGB 132 | { 133 | R = 64 134 | G = 189 135 | B = 114 136 | } 137 | } 138 | ControlPoint 9 139 | { 140 | ColorMapFraction = 0.7959 141 | LeadRGB 142 | { 143 | R = 119 144 | G = 209 145 | B = 83 146 | } 147 | TrailRGB 148 | { 149 | R = 119 150 | G = 209 151 | B = 83 152 | } 153 | } 154 | ControlPoint 10 155 | { 156 | ColorMapFraction = 0.898 157 | LeadRGB 158 | { 159 | R = 186 160 | G = 222 161 | B = 40 162 | } 163 | TrailRGB 164 | { 165 | R = 186 166 | G = 222 167 | B = 40 168 | } 169 | } 170 | ControlPoint 11 171 | { 172 | ColorMapFraction = 1 173 | LeadRGB 174 | { 175 | R = 253 176 | G = 231 177 | B = 37 178 | } 179 | TrailRGB 180 | { 181 | R = 253 182 | G = 231 183 | B = 37 184 | } 185 | } 186 | $!GlobalPaper 187 | PaperSizeInfo 188 | { 189 | Letter 190 | { 191 | Width = 8.5 192 | Height = 11 193 | LeftHardClipOffset = 0.125 194 | RightHardClipOffset = 0.125 195 | TopHardClipOffset = 0.125 196 | BottomHardClipOffset = 0.125 197 | } 198 | } 199 | $!Page 200 | Name = 'Untitled' 201 | PaperAttributes 202 | { 203 | BackgroundColor = White 204 | IsTransparent = Yes 205 | OrientPortrait = No 206 | ShowGrid = Yes 207 | ShowRuler = No 208 | ShowPaper = No 209 | PaperSize = Letter 210 | RulerSpacing = OneInch 211 | PaperGridSpacing = HalfInch 212 | RegionInWorkArea 213 | { 214 | X1 = 1 215 | Y1 = 0.25 216 | X2 = 10 217 | Y2 = 8.25 218 | } 219 | } 220 | ### Frame Number 1 ### 221 | $!ReadDataSet '|LFDSFN1|' 222 | InitialPlotType = Cartesian3D 223 | IncludeText = No 224 | IncludeGeom = No 225 | AssignStrandIDs = Yes 226 | VarLoadMode = ByName 227 | VarNameList = '|LFDSVL1|' 228 | $!RemoveVar |LFDSVL1| 229 | $!RemoveVar |LFDSFN1| 230 | $!ReadDataSet '|LFDSFN2|' 231 | InitialPlotType = Cartesian3D 232 | IncludeText = No 233 | IncludeGeom = No 234 | ReadDataOption = Append 235 | ResetStyle = No 236 | AssignStrandIDs = Yes 237 | VarLoadMode = ByName 238 | VarNameList = '|LFDSVL2|' 239 | $!RemoveVar |LFDSVL2| 240 | $!RemoveVar |LFDSFN2| 241 | $!FrameLayout 242 | ShowHeader = No 243 | HeaderColor = Red 244 | XYPos 245 | { 246 | X = 1 247 | Y = 0.25 248 | } 249 | Width = 9 250 | Height = 8 251 | $!ThreeDAxis 252 | AspectRatioLimit = 25 253 | BoxAspectRatioLimit = 25 254 | $!PlotType = Cartesian3D 255 | $!FrameName = 'Frame 001' 256 | $!GlobalTime 257 | SolutionTime = 0 258 | $!ActiveFieldMaps = [1,4-5] 259 | $!GlobalRGB 260 | RangeMin = 0 261 | RangeMax = 1 262 | $!GlobalContour 1 263 | ColorMapName = 'Sequential - Viridis' 264 | Legend 265 | { 266 | Show = Yes 267 | XYPos 268 | { 269 | X = 95 270 | } 271 | } 272 | ColorMapFilter 273 | { 274 | ContinuousColor 275 | { 276 | CMin = 0 277 | CMax = 1 278 | } 279 | } 280 | $!GlobalContour 2 281 | ColorMapName = 'Sequential - Viridis' 282 | Legend 283 | { 284 | Show = Yes 285 | XYPos 286 | { 287 | X = 95 288 | } 289 | } 290 | ColorMapFilter 291 | { 292 | ContinuousColor 293 | { 294 | CMin = 0 295 | CMax = 1 296 | } 297 | } 298 | $!GlobalContour 3 299 | ColorMapName = 'Sequential - Viridis' 300 | Legend 301 | { 302 | Show = Yes 303 | XYPos 304 | { 305 | X = 95 306 | } 307 | } 308 | ColorMapFilter 309 | { 310 | ContinuousColor 311 | { 312 | CMin = 0 313 | CMax = 1 314 | } 315 | } 316 | $!GlobalContour 4 317 | ColorMapName = 'Sequential - Viridis' 318 | Legend 319 | { 320 | Show = Yes 321 | XYPos 322 | { 323 | X = 95 324 | } 325 | } 326 | ColorMapFilter 327 | { 328 | ContinuousColor 329 | { 330 | CMin = 0 331 | CMax = 1 332 | } 333 | } 334 | $!GlobalContour 5 335 | ColorMapName = 'Sequential - Viridis' 336 | Legend 337 | { 338 | Show = Yes 339 | XYPos 340 | { 341 | X = 95 342 | } 343 | } 344 | ColorMapFilter 345 | { 346 | ContinuousColor 347 | { 348 | CMin = 0 349 | CMax = 1 350 | } 351 | } 352 | $!GlobalContour 6 353 | ColorMapName = 'Sequential - Viridis' 354 | Legend 355 | { 356 | Show = Yes 357 | XYPos 358 | { 359 | X = 95 360 | } 361 | } 362 | ColorMapFilter 363 | { 364 | ContinuousColor 365 | { 366 | CMin = 0 367 | CMax = 1 368 | } 369 | } 370 | $!GlobalContour 7 371 | ColorMapName = 'Sequential - Viridis' 372 | Legend 373 | { 374 | Show = Yes 375 | XYPos 376 | { 377 | X = 95 378 | } 379 | } 380 | ColorMapFilter 381 | { 382 | ContinuousColor 383 | { 384 | CMin = 0 385 | CMax = 1 386 | } 387 | } 388 | $!GlobalContour 8 389 | ColorMapName = 'Sequential - Viridis' 390 | Legend 391 | { 392 | Show = Yes 393 | XYPos 394 | { 395 | X = 95 396 | } 397 | } 398 | ColorMapFilter 399 | { 400 | ContinuousColor 401 | { 402 | CMin = 0 403 | CMax = 1 404 | } 405 | } 406 | $!GlobalScatter 407 | Var = 3 408 | RelativeSize = 0.03436 409 | Legend 410 | { 411 | XYPos 412 | { 413 | X = 95 414 | } 415 | } 416 | RefScatSymbol 417 | { 418 | Color = Red 419 | FillColor = Red 420 | } 421 | $!FieldMap [1-3] 422 | Mesh 423 | { 424 | Color = Black 425 | } 426 | Contour 427 | { 428 | ContourType = Flood 429 | Color = Black 430 | UseLightingEffect = Yes 431 | } 432 | Vector 433 | { 434 | Color = Black 435 | } 436 | Scatter 437 | { 438 | Show = No 439 | Color = Black 440 | } 441 | Shade 442 | { 443 | Color = Custom2 444 | } 445 | EdgeLayer 446 | { 447 | Show = Yes 448 | Color = Black 449 | LineThickness = 0.1 450 | } 451 | Points 452 | { 453 | PointsToPlot = SurfaceNodes 454 | } 455 | Surfaces 456 | { 457 | SurfacesToPlot = BoundaryFaces 458 | IRange 459 | { 460 | Max = 1 461 | } 462 | } 463 | Effects 464 | { 465 | LightingEffect = Gouraud 466 | } 467 | $!FieldMap [4] 468 | Mesh 469 | { 470 | Show = No 471 | Color = Black 472 | } 473 | Contour 474 | { 475 | ContourType = Flood 476 | Color = Black 477 | UseLightingEffect = Yes 478 | } 479 | Vector 480 | { 481 | Color = Black 482 | } 483 | Scatter 484 | { 485 | SymbolShape 486 | { 487 | GeomShape = Sphere 488 | } 489 | Color = Red 490 | } 491 | Shade 492 | { 493 | Color = Custom2 494 | } 495 | EdgeLayer 496 | { 497 | Show = No 498 | Color = Black 499 | LineThickness = 0.1 500 | } 501 | Points 502 | { 503 | PointsToPlot = SurfaceNodes 504 | } 505 | Surfaces 506 | { 507 | SurfacesToPlot = KPlanes 508 | IRange 509 | { 510 | Max = 1 511 | } 512 | } 513 | VolumeMode 514 | { 515 | VolumeObjectsToPlot 516 | { 517 | ShowIsosurfaces = No 518 | ShowSlices = No 519 | ShowStreamtraces = No 520 | } 521 | } 522 | Effects 523 | { 524 | LightingEffect = Gouraud 525 | } 526 | $!FieldMap [5] 527 | Mesh 528 | { 529 | Show = No 530 | Color = Yellow 531 | } 532 | Contour 533 | { 534 | Color = Yellow 535 | } 536 | Vector 537 | { 538 | Color = Yellow 539 | } 540 | Scatter 541 | { 542 | SymbolShape 543 | { 544 | GeomShape = Sphere 545 | } 546 | Color = Yellow 547 | } 548 | Shade 549 | { 550 | Color = Custom2 551 | } 552 | EdgeLayer 553 | { 554 | Show = Yes 555 | Color = Yellow 556 | } 557 | Points 558 | { 559 | PointsToPlot = SurfaceNodes 560 | } 561 | Surfaces 562 | { 563 | SurfacesToPlot = KPlanes 564 | } 565 | $!ThreeDAxis 566 | XDetail 567 | { 568 | VarNum = 1 569 | } 570 | YDetail 571 | { 572 | VarNum = 2 573 | } 574 | ZDetail 575 | { 576 | VarNum = 3 577 | } 578 | $!View Fit 579 | $!ThreeDAxis 580 | AxisMode = XYZDependent 581 | XYDepXToYRatio = 1 582 | DepXToYRatio = 1 583 | DepXToZRatio = 1 584 | $!ThreeDAxis 585 | XDetail 586 | { 587 | ShowAxis = No 588 | RangeMin = -0.27000000000000001776 589 | RangeMax = 1.2700000000000000178 590 | GRSpacing = 0.5 591 | AxisLine 592 | { 593 | Edge = 2 594 | } 595 | } 596 | $!ThreeDAxis 597 | YDetail 598 | { 599 | ShowAxis = No 600 | RangeMin = -0.2750000000000000222 601 | RangeMax = 1.375 602 | GRSpacing = 0.5 603 | AxisLine 604 | { 605 | Edge = 3 606 | } 607 | } 608 | $!ThreeDAxis 609 | ZDetail 610 | { 611 | ShowAxis = No 612 | RangeMin = -0.21000000000000001998 613 | RangeMax = 2.2099999999999999645 614 | GRSpacing = 0.5 615 | AxisLine 616 | { 617 | Edge = 2 618 | } 619 | } 620 | $!IsoSurfaceAttributes 1 621 | IsoSurfaceSelection = OneSpecificValue 622 | Effects 623 | { 624 | LightingEffect = Gouraud 625 | } 626 | $!IsoSurfaceAttributes 2 627 | DefinitionContourGroup = 2 628 | IsoSurfaceSelection = OneSpecificValue 629 | Contour 630 | { 631 | LineContourGroup = 2 632 | FloodColoring = Group2 633 | } 634 | Effects 635 | { 636 | LightingEffect = Gouraud 637 | } 638 | $!IsoSurfaceAttributes 3 639 | DefinitionContourGroup = 3 640 | IsoSurfaceSelection = OneSpecificValue 641 | Contour 642 | { 643 | LineContourGroup = 3 644 | FloodColoring = Group3 645 | } 646 | Effects 647 | { 648 | LightingEffect = Gouraud 649 | } 650 | $!IsoSurfaceAttributes 4 651 | DefinitionContourGroup = 4 652 | IsoSurfaceSelection = OneSpecificValue 653 | Contour 654 | { 655 | LineContourGroup = 4 656 | FloodColoring = Group4 657 | } 658 | Effects 659 | { 660 | LightingEffect = Gouraud 661 | } 662 | $!IsoSurfaceAttributes 5 663 | DefinitionContourGroup = 5 664 | IsoSurfaceSelection = OneSpecificValue 665 | Contour 666 | { 667 | LineContourGroup = 5 668 | FloodColoring = Group5 669 | } 670 | Effects 671 | { 672 | LightingEffect = Gouraud 673 | } 674 | $!IsoSurfaceAttributes 6 675 | DefinitionContourGroup = 6 676 | IsoSurfaceSelection = OneSpecificValue 677 | Contour 678 | { 679 | LineContourGroup = 6 680 | FloodColoring = Group6 681 | } 682 | Effects 683 | { 684 | LightingEffect = Gouraud 685 | } 686 | $!IsoSurfaceAttributes 7 687 | DefinitionContourGroup = 7 688 | IsoSurfaceSelection = OneSpecificValue 689 | Contour 690 | { 691 | LineContourGroup = 7 692 | FloodColoring = Group7 693 | } 694 | Effects 695 | { 696 | LightingEffect = Gouraud 697 | } 698 | $!IsoSurfaceAttributes 8 699 | DefinitionContourGroup = 8 700 | IsoSurfaceSelection = OneSpecificValue 701 | Contour 702 | { 703 | LineContourGroup = 8 704 | FloodColoring = Group8 705 | } 706 | Effects 707 | { 708 | LightingEffect = Gouraud 709 | } 710 | $!SliceAttributes 1 711 | PrimaryPosition 712 | { 713 | X = 0 714 | Y = 0 715 | Z = 0 716 | I = 1 717 | J = 1 718 | K = 1 719 | } 720 | StartPosition 721 | { 722 | X = -0.13 723 | Y = -0.125 724 | Z = 0.01 725 | } 726 | EndPosition 727 | { 728 | X = 1.13 729 | Y = 1.225 730 | Z = 1.99 731 | I = 2 732 | J = 2 733 | K = 2 734 | } 735 | EdgeLayer 736 | { 737 | Show = No 738 | } 739 | Effects 740 | { 741 | LightingEffect = Gouraud 742 | SurfaceTranslucency = 10 743 | } 744 | SliceConstraint 745 | { 746 | Include = No 747 | Origin 748 | { 749 | X = 0 750 | Y = 0 751 | Z = 0 752 | } 753 | BoxDimension 754 | { 755 | X = 0 756 | Y = 0 757 | Z = 0 758 | } 759 | } 760 | $!SliceAttributes 2 761 | SliceSurface = YPlanes 762 | EdgeLayer 763 | { 764 | Show = No 765 | } 766 | Effects 767 | { 768 | LightingEffect = Gouraud 769 | SurfaceTranslucency = 10 770 | } 771 | $!SliceAttributes 3 772 | SliceSurface = ZPlanes 773 | EdgeLayer 774 | { 775 | Show = No 776 | } 777 | Effects 778 | { 779 | LightingEffect = Gouraud 780 | SurfaceTranslucency = 10 781 | } 782 | $!SliceAttributes 4 783 | EdgeLayer 784 | { 785 | Show = No 786 | } 787 | Effects 788 | { 789 | LightingEffect = Gouraud 790 | SurfaceTranslucency = 10 791 | } 792 | $!SliceAttributes 5 793 | SliceSurface = YPlanes 794 | EdgeLayer 795 | { 796 | Show = No 797 | } 798 | Effects 799 | { 800 | LightingEffect = Gouraud 801 | SurfaceTranslucency = 10 802 | } 803 | $!SliceAttributes 6 804 | SliceSurface = ZPlanes 805 | EdgeLayer 806 | { 807 | Show = No 808 | } 809 | Effects 810 | { 811 | LightingEffect = Gouraud 812 | SurfaceTranslucency = 10 813 | } 814 | $!SliceAttributes 7 815 | EdgeLayer 816 | { 817 | Show = No 818 | } 819 | Effects 820 | { 821 | LightingEffect = Gouraud 822 | SurfaceTranslucency = 10 823 | } 824 | $!SliceAttributes 8 825 | SliceSurface = YPlanes 826 | EdgeLayer 827 | { 828 | Show = No 829 | } 830 | Effects 831 | { 832 | LightingEffect = Gouraud 833 | SurfaceTranslucency = 10 834 | } 835 | $!StreamAttributes 836 | StreamTiming 837 | { 838 | MarkSize = 1 839 | MarkSymbol 840 | { 841 | GeomShape = Sphere 842 | } 843 | } 844 | RodRibbon 845 | { 846 | Effects 847 | { 848 | LightingEffect = Gouraud 849 | } 850 | } 851 | MaxSteps = 10000 852 | $!GlobalThreeD 853 | AxisScaleFact 854 | { 855 | X = 1 856 | Y = 1 857 | Z = 1 858 | } 859 | RotateOrigin 860 | { 861 | X = 0.5 862 | Y = 0.55 863 | Z = 1 864 | } 865 | LightSource 866 | { 867 | XYZDirection 868 | { 869 | X = -0.2 870 | Y = -0.2 871 | Z = 0.9591663046625438 872 | } 873 | Intensity = 75 874 | BackgroundLight = 25 875 | IncludeSpecular = Yes 876 | SpecularIntensity = 40 877 | SpecularShininess = 60 878 | } 879 | LineLiftFraction = 0.2 880 | SymbolLiftFraction = 0.6 881 | VectorLiftFraction = 0.7 882 | NearPlaneFraction = 0.1 883 | $!ThreeDView 884 | PSIAngle = 56.3058 885 | ThetaAngle = -133.855 886 | AlphaAngle = 1.31053 887 | ViewerPosition 888 | { 889 | X = 10.49929340457024 890 | Y = 10.28399646540389 891 | Z = 10.34966535577423 892 | } 893 | ViewWidth = 2.60994 894 | $!FieldLayers 895 | ShowScatter = Yes 896 | ShowShade = Yes 897 | ShowEdge = No 898 | UseTranslucency = Yes 899 | $!StreamtraceLayers 900 | Show = No 901 | $!FrameControl ActivateByNumber 902 | Frame = 1 903 | $!SetStyleBase Config 904 | -------------------------------------------------------------------------------- /lib/Makefile: -------------------------------------------------------------------------------- 1 | MAIN_DIR = .. 2 | COMMON_FILE = $(MAIN_DIR)/Common.mk 3 | include ${COMMON_FILE} 4 | 5 | default: makelib 6 | 7 | clean: 8 | @echo " Making clean in lib ... " 9 | rm -f lib/* 10 | 11 | # ****************************************************************** 12 | # * * 13 | # * Rule to make the library. * 14 | # * * 15 | # ****************************************************************** 16 | 17 | makelib: 18 | @echo " creating library ..." 19 | @echo 20 | $(AR) $(AR_FLAGS) libspline.a $(OBJDIR)/*.o 21 | @echo 22 | @echo " library libspline.a created." 23 | @echo 24 | -------------------------------------------------------------------------------- /mod/README: -------------------------------------------------------------------------------- 1 | This is just a placeholder file to convince mercurial the directory is not empty -------------------------------------------------------------------------------- /pyspline/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "1.5.3" 2 | 3 | from .pyCurve import Curve 4 | from .pySurface import Surface 5 | from .pyVolume import Volume 6 | -------------------------------------------------------------------------------- /pyspline/utils.py: -------------------------------------------------------------------------------- 1 | # External modules 2 | import numpy as np 3 | from scipy import sparse 4 | 5 | # Local modules 6 | from . import libspline 7 | 8 | 9 | class Error(Exception): 10 | """ 11 | Format the error message in a box to make it clear this 12 | was a explicitly raised exception. 13 | """ 14 | 15 | def __init__(self, message): 16 | msg = "\n+" + "-" * 78 + "+" + "\n" + "| pySpline Error: " 17 | i = 17 18 | for word in message.split(): 19 | if len(word) + i + 1 > 78: # Finish line and start new one 20 | msg += " " * (78 - i) + "|\n| " + word + " " 21 | i = 1 + len(word) + 1 22 | else: 23 | msg += word + " " 24 | i += len(word) + 1 25 | msg += " " * (78 - i) + "|\n" + "+" + "-" * 78 + "+" + "\n" 26 | print(msg) 27 | Exception.__init__() 28 | 29 | 30 | def writeTecplot1D(handle, name, data, solutionTime=None): 31 | """A Generic function to write a 1D data zone to a tecplot file. 32 | 33 | Parameters 34 | ---------- 35 | handle : file handle 36 | Open file handle 37 | name : str 38 | Name of the zone to use 39 | data : array of size (N, ndim) 40 | 1D array of data to write to file 41 | SolutionTime : float 42 | Solution time to write to the file. This could be a fictitious time to 43 | make visualization easier in tecplot. 44 | """ 45 | nx = data.shape[0] 46 | ndim = data.shape[1] 47 | handle.write('Zone T="%s" I=%d\n' % (name, nx)) 48 | if solutionTime is not None: 49 | handle.write("SOLUTIONTIME=%f\n" % (solutionTime)) 50 | handle.write("DATAPACKING=POINT\n") 51 | for i in range(nx): 52 | for idim in range(ndim): 53 | handle.write("%f " % (data[i, idim])) 54 | handle.write("\n") 55 | 56 | 57 | def writeTecplot2D(handle, name, data, solutionTime=None): 58 | """A Generic function to write a 2D data zone to a tecplot file. 59 | 60 | Parameters 61 | ---------- 62 | handle : file handle 63 | Open file handle 64 | name : str 65 | Name of the zone to use 66 | data : 2D np array of size (nx, ny, ndim) 67 | 2D array of data to write to file 68 | SolutionTime : float 69 | Solution time to write to the file. This could be a fictitious time to 70 | make visualization easier in tecplot. 71 | """ 72 | nx = data.shape[0] 73 | ny = data.shape[1] 74 | ndim = data.shape[2] 75 | handle.write('Zone T="%s" I=%d J=%d\n' % (name, nx, ny)) 76 | if solutionTime is not None: 77 | handle.write("SOLUTIONTIME=%f\n" % (solutionTime)) 78 | handle.write("DATAPACKING=POINT\n") 79 | for j in range(ny): 80 | for i in range(nx): 81 | for idim in range(ndim): 82 | handle.write("%20.16g " % (data[i, j, idim])) 83 | handle.write("\n") 84 | 85 | 86 | def writeTecplot3D(handle, name, data, solutionTime=None): 87 | """A Generic function to write a 3D data zone to a tecplot file. 88 | 89 | Parameters 90 | ---------- 91 | handle : file handle 92 | Open file handle 93 | name : str 94 | Name of the zone to use 95 | data : 3D np array of size (nx, ny, nz, ndim) 96 | 3D array of data to write to file 97 | SolutionTime : float 98 | Solution time to write to the file. This could be a fictitious time to 99 | make visualization easier in tecplot. 100 | """ 101 | nx = data.shape[0] 102 | ny = data.shape[1] 103 | nz = data.shape[2] 104 | ndim = data.shape[3] 105 | handle.write('Zone T="%s" I=%d J=%d K=%d\n' % (name, nx, ny, nz)) 106 | if solutionTime is not None: 107 | handle.write("SOLUTIONTIME=%f\n" % (solutionTime)) 108 | handle.write("DATAPACKING=POINT\n") 109 | for k in range(nz): 110 | for j in range(ny): 111 | for i in range(nx): 112 | for idim in range(ndim): 113 | handle.write("%f " % (data[i, j, k, idim])) 114 | handle.write("\n") 115 | 116 | 117 | def _writeHeader(f, ndim): 118 | """Write tecplot zone header depending on spatial dimension""" 119 | if ndim == 1: 120 | f.write('VARIABLES = "CoordinateX"\n') 121 | elif ndim == 2: 122 | f.write('VARIABLES = "CoordinateX", "CoordinateY"\n') 123 | else: 124 | f.write('VARIABLES = "CoordinateX", "CoordinateY", "CoordinateZ"\n') 125 | 126 | 127 | def openTecplot(fileName, ndim): 128 | """A Generic function to open a Tecplot file to write spatial data. 129 | 130 | Parameters 131 | ---------- 132 | fileName : str 133 | Tecplot filename. Should have a .dat extension. 134 | ndim : int 135 | Number of spatial dimensions. Must be 1, 2 or 3. 136 | 137 | Returns 138 | ------- 139 | f : file handle 140 | Open file handle 141 | """ 142 | f = open(fileName, "w") 143 | _writeHeader(f, ndim) 144 | 145 | return f 146 | 147 | 148 | def closeTecplot(f): 149 | """Close Tecplot file opened with openTecplot()""" 150 | f.close() 151 | 152 | 153 | def _assembleMatrix(data, indices, indptr, shape): 154 | """ 155 | Generic assemble matrix function to create a CSR matrix 156 | 157 | Parameters 158 | ---------- 159 | data : array 160 | Data values for matrix 161 | indices : int array 162 | CSR type indices 163 | indptr : int array 164 | Row pointer 165 | shape : tuple-like 166 | Actual shape of matrix 167 | 168 | Returns 169 | ------- 170 | M : scipy csr sparse matrix 171 | The assembled matrix 172 | """ 173 | M = sparse.csr_matrix((data, indices, indptr), shape) 174 | 175 | return M 176 | 177 | 178 | def checkInput(inputVal, inputName, dataType, dataRank, dataShape=None): 179 | """This is a generic function to check the data type and sizes of 180 | inputs in functions where the user must supply proper 181 | values. Since Python does not do type checking on Inputs, this is 182 | required 183 | 184 | Parameters 185 | ---------- 186 | input : int, float, or complex 187 | The input argument to check 188 | inputName : str 189 | The name of the variable, so it can be identified in an Error message 190 | dataType : str 191 | Numpy string dtype code 192 | dataRank : int 193 | Desired rank. 0 for scalar, 1 for vector 2 for matrix etc 194 | dataShape : tuple 195 | The required shape of the data. 196 | Scalar is denoted by () 197 | Vector is denoted by (n, ) where n is the shape 198 | Matrix is denoted by (n, m) where n and m are rows/columns 199 | 200 | Returns 201 | ------- 202 | output : various 203 | The input transformed to the correct type and guaranteed to 204 | the desired size and shape. 205 | """ 206 | 207 | # Check the data rank: 208 | rank = np.ndim(inputVal) 209 | if rank != dataRank: 210 | raise Error("'%s' must have rank %d. Input was of rank %d." % (inputName, dataRank, rank)) 211 | 212 | # Check the data type 213 | inputVal = np.array(inputVal) 214 | tmp = inputVal.astype(dataType) 215 | 216 | # Check if the values are the same: 217 | diff = (tmp - inputVal).flatten() 218 | if np.dot(diff, diff) > 10 * np.finfo(1.0).eps: 219 | raise Error("'%s' could not be safely cast to required type without losing information" % inputName) 220 | 221 | # Finally check that the shape is correct: 222 | if dataShape is not None: 223 | if tmp.shape != tuple(dataShape): 224 | raise Error( 225 | "'%s' was not the correct shape. Input was shape " 226 | "%s while requested dataShape was '%s'." % (inputName, repr(tmp.shape), repr(dataShape)) 227 | ) 228 | if dataRank == 0: 229 | return tmp.squeeze() 230 | else: 231 | return tmp 232 | 233 | 234 | def trilinearVolume(*args): 235 | """This is a short-cut function to create a trilinear b-spline 236 | volume. It can be created with ``x`` **OR** with ``xmin`` and 237 | ``xmax``. 238 | 239 | Parameters 240 | ---------- 241 | x : array of size (2, 2, 2, 3) 242 | Coordinates of the corners of the box. 243 | 244 | xmin : array of size (3) 245 | The extreme lower corner of the box 246 | xmax : array of size (3) 247 | The extreme upper corner of the box. In this case, by 248 | construction, the box will be coordinate axis aligned. 249 | """ 250 | # Local modules 251 | from .pyVolume import Volume 252 | 253 | tu = [0, 0, 1, 1] 254 | tv = [0, 0, 1, 1] 255 | tw = [0, 0, 1, 1] 256 | ku = 2 257 | kv = 2 258 | kw = 2 259 | 260 | if len(args) == 1: 261 | return Volume(coef=args[0], tu=tu, tv=tv, tw=tw, ku=ku, kv=kv, kw=kw) 262 | elif len(args) == 2: 263 | xmin = np.array(args[0]).astype("d") 264 | xmax = np.array(args[1]).astype("d") 265 | 266 | xLow = xmin[0] 267 | xHigh = xmax[0] 268 | yLow = xmin[1] 269 | yHigh = xmax[1] 270 | zLow = xmin[2] 271 | zHigh = xmax[2] 272 | 273 | coef = np.zeros((2, 2, 2, 3)) 274 | coef[0, 0, 0, :] = [xLow, yLow, zLow] 275 | coef[1, 0, 0, :] = [xHigh, yLow, zLow] 276 | coef[0, 1, 0, :] = [xLow, yHigh, zLow] 277 | coef[1, 1, 0, :] = [xHigh, yHigh, zLow] 278 | coef[0, 0, 1, :] = [xLow, yLow, zHigh] 279 | coef[1, 0, 1, :] = [xHigh, yLow, zHigh] 280 | coef[0, 1, 1, :] = [xLow, yHigh, zHigh] 281 | coef[1, 1, 1, :] = [xHigh, yHigh, zHigh] 282 | 283 | return Volume(coef=coef, tu=tu, tv=tv, tw=tw, ku=ku, kv=kv, kw=kw) 284 | else: 285 | raise Error("An unknown number of arguments was passed to trilinear Volume") 286 | 287 | 288 | def bilinearSurface(*args): 289 | """This is short-cut function to create a bilinear surface. 290 | 291 | Args can contain: 292 | 293 | 1. ``x`` array of size(4, 3). The four corners of the array 294 | arranged in the coordinate direction orientation:: 295 | 296 | 2 3 297 | +----------+ 298 | | | 299 | | | 300 | | | 301 | +----------+ 302 | 0 1 303 | 304 | 2. ``p1``, ``p2``, ``p3``, ``p4``. Individual corner points in CCW Ordering:: 305 | 306 | 3 2 307 | +----------+ 308 | | | 309 | | | 310 | | | 311 | +----------+ 312 | 0 1 313 | """ 314 | # Local modules 315 | from .pySurface import Surface 316 | 317 | if len(args) == 1: 318 | # One argument passed in ... assume its X 319 | if len(args[0]) != 4: 320 | raise Error("A single argument passed to bilinear surface must contain 4 points and be of size (4, 3)") 321 | coef = np.zeros((2, 2, 3)) 322 | coef[0, 0] = args[0][0] 323 | coef[1, 0] = args[0][1] 324 | coef[0, 1] = args[0][2] 325 | coef[1, 1] = args[0][3] 326 | return Surface(coef=coef, tu=[0, 0, 1, 1], tv=[0, 0, 1, 1], ku=2, kv=2) 327 | else: 328 | # Assume 4 arguments 329 | coef = np.zeros([2, 2, 3]) 330 | coef[0, 0] = args[0] 331 | coef[1, 0] = args[1] 332 | coef[0, 1] = args[3] 333 | coef[1, 1] = args[2] 334 | return Surface(coef=coef, tu=[0, 0, 1, 1], tv=[0, 0, 1, 1], ku=2, kv=2) 335 | 336 | 337 | def line(*args, **kwargs): 338 | """This is a short cut function to create a line as a pySpline Curve object. 339 | 340 | Args can contain: (pick one) 341 | 342 | 1. ``X`` array of size(2, ndim). The two end points 343 | 2. ``x1``, ``x2`` The two end points (each of size ndim) 344 | 3. ``x```, dir=direction. A point and a displacement vector 345 | 4. ``x1``, dir=direction, length=length. As 3. but with a specific length 346 | """ 347 | # Local modules 348 | from .pyCurve import Curve 349 | 350 | if len(args) == 2: 351 | # Its a two-point type 352 | return Curve(coef=[args[0], args[1]], k=2, t=[0, 0, 1, 1]) 353 | elif len(args) == 1: 354 | if len(args[0]) == 2: # its X 355 | return Curve(coef=args[0], k=2, t=[0, 0, 1, 1]) 356 | elif "dir" in kwargs: 357 | # We have point and direction 358 | if "length" in kwargs: 359 | x2 = args[0] + kwargs["dir"] / np.linalg.norm(kwargs["dir"]) * kwargs["length"] 360 | else: 361 | x2 = args[0] + kwargs["dir"] 362 | 363 | return Curve(coef=[args[0], x2], k=2, t=[0, 0, 1, 1]) 364 | else: 365 | Error("Error: dir must be specified if only 1 argument is given") 366 | 367 | 368 | def plane_line(ia, vc, p0, v1, v2): 369 | """ 370 | Check a plane against multiple lines 371 | 372 | Parameters 373 | ---------- 374 | ia : ndarray[3, n] 375 | initial point 376 | vc : ndarray[3, n] 377 | search vector from initial point 378 | p0 : ndarray[3] 379 | vector to triangle origins 380 | v1 : ndarray[3] 381 | vector along first triangle direction 382 | v2 : ndarray[3] 383 | vector along second triangle direction 384 | 385 | Returns 386 | ------- 387 | sol : ndarray[6, n] 388 | Solution vector - parametric positions + physical coordiantes 389 | nSol : int 390 | Number of solutions 391 | """ 392 | 393 | return libspline.plane_line(ia, vc, p0, v1, v2) 394 | 395 | 396 | def tfi2d(e0, e1, e2, e3): 397 | """ 398 | Perform a simple 2D transfinite interpolation in 3D. 399 | 400 | Parameters 401 | ---------- 402 | e0 : ndarray[3, Nu] 403 | coordinates along 0th edge 404 | e1 : ndarray[3, Nu] 405 | coordinates along 1st edge 406 | e2 : ndarray[3, Nv] 407 | coordinates along 2nd edge 408 | e3 : ndarray[3, Nv] 409 | coordinates along 3rd edge 410 | 411 | Returns 412 | ------- 413 | X : ndarray[3 x Nu x Nv] 414 | evaluated points 415 | """ 416 | return libspline.tfi2d(e0, e1, e2, e3) 417 | 418 | 419 | def line_plane(ia, vc, p0, v1, v2): 420 | r""" 421 | Check a line against multiple planes. 422 | Solve for the scalars :math:`\alpha, \beta, \gamma` such that 423 | 424 | .. math:: 425 | 426 | i_a + \alpha \times v_c &= p_0 + \beta \times v_1 + \gamma \times v_2 \\ 427 | i_a - p_0 &= \begin{bmatrix}-v_c & v_1 & v_2\end{bmatrix}\begin{bmatrix}\alpha\\\beta\\\gamma\end{bmatrix}\\ 428 | \alpha &\ge 0: \text{The point lies above the initial point}\\ 429 | \alpha &< 0: \text{The point lies below the initial point} 430 | 431 | The domain of the triangle is defined by 432 | 433 | .. math:: 434 | 435 | \beta + \gamma = 1 436 | 437 | and 438 | 439 | .. math:: 440 | 441 | 0 < \beta, \gamma < 1 442 | 443 | Parameters 444 | ---------- 445 | ia : ndarray[3] 446 | initial point 447 | vc : ndarray[3] 448 | search vector from initial point 449 | p0 : ndarray[3, n] 450 | vector to triangle origins 451 | v1 : ndarray[3, n] 452 | vector along first triangle direction 453 | v2 : ndarray[3, n] 454 | vector along second triangle direction 455 | 456 | Returns 457 | ------- 458 | sol : real ndarray[6, n] 459 | Solution vector---parametric positions + physical coordinates 460 | pid : int ndarray[n] 461 | Id for a given solution 462 | nSol : int 463 | Number of solutions 464 | """ 465 | 466 | return libspline.line_plane(ia, vc, p0, v1, v2) 467 | 468 | 469 | def searchQuads(pts, conn, searchPts): 470 | """ 471 | This routine searches for the closest point on a set of quads for each searchPt. 472 | An ADT tree is built and used for the search and subsequently destroyed. 473 | 474 | Parameters 475 | ---------- 476 | pts : ndarray[3, nPts] 477 | points defining the quad elements 478 | conn : ndarray[4, nConn] 479 | local connectivity of the quad elements 480 | searchPts : ndarray[3, nSearchPts] 481 | set of points to search for 482 | 483 | Returns 484 | ------- 485 | faceID : ndarray[nSearchPts] 486 | index of the quad elements, one for each search point 487 | uv : ndarray[2, nSearchPts] 488 | parametric ``u`` and ``v`` weights of the projected point on the closest quad 489 | """ 490 | 491 | return libspline.adtprojections.searchquads(pts, conn, searchPts) 492 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | import re 3 | import os 4 | 5 | __version__ = re.findall( 6 | r"""__version__ = ["']+([0-9\.]*)["']+""", 7 | open("pyspline/__init__.py").read(), 8 | )[0] 9 | 10 | this_directory = os.path.abspath(os.path.dirname(__file__)) 11 | with open(os.path.join(this_directory, "README.md"), encoding="utf-8") as f: 12 | long_description = f.read() 13 | 14 | with open("doc/requirements.txt") as f: 15 | docs_require = f.read().splitlines() 16 | 17 | setup( 18 | name="pyspline", 19 | version=__version__, 20 | description="pySpline is a package containing code for working with b-spline curve, surface, and volume objects", 21 | long_description=long_description, 22 | long_description_content_type="text/markdown", 23 | keywords="spline b-spline optimization", 24 | author="", 25 | author_email="", 26 | url="https://github.com/mdolab/pyspline", 27 | license="Apache License Version 2.0", 28 | packages=["pyspline"], 29 | package_data={"pyspline": ["*.so"]}, 30 | install_requires=["numpy>=1.21", "scipy>=1.7"], 31 | extras_require={ 32 | "docs": docs_require, 33 | "testing": ["parameterized", "testflo>=1.4.5", "mdolab-baseclasses>=1.6.1"], 34 | }, 35 | classifiers=["Operating System :: Linux", "Programming Language :: Python, Fortran"], 36 | ) 37 | -------------------------------------------------------------------------------- /src/Makefile: -------------------------------------------------------------------------------- 1 | #********************************************************* 2 | # Makefile for pySpline 3 | # G. Kenway May 21, 2009 4 | #********************************************************* 5 | 6 | MAIN_DIR = ../ 7 | COMMON_FILE = $(MAIN_DIR)/Common.mk 8 | RULES_FILE = $(MAIN_DIR)/Rules.mk 9 | include ${COMMON_FILE} 10 | include ${RULES_FILE} 11 | vpath %.o $(OBJDIR) 12 | 13 | # Name of files to be compiled: 14 | MODS = precision.o\ 15 | adtProjections.o 16 | 17 | OBJS = evaluations.o\ 18 | basis.o\ 19 | knots.o\ 20 | insertKnot.o\ 21 | getBasisPt.o\ 22 | parameterizations.o\ 23 | findSpan.o\ 24 | compute_curve.o\ 25 | compute_surface.o\ 26 | compute_volume.o\ 27 | eval_curve.o\ 28 | eval_surface.o\ 29 | eval_volume.o\ 30 | projections.o\ 31 | tfi2d.o\ 32 | 33 | default: 34 | $(MAKE) $(MODS) 35 | cp -f *.mod ../mod 36 | $(MAKE) $(OBJS) 37 | 38 | clean: 39 | @echo " Making clean in src... " 40 | rm -f $(MAKE_CLEAN_ARGUMENTS) 41 | -------------------------------------------------------------------------------- /src/basis.f90: -------------------------------------------------------------------------------- 1 | subroutine basis(t, nctl, k, u, ind, B) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract: basis evaluates the standard b-spline basis 8 | ! functions at a location x for knot vector t. Adapted 9 | ! from The NURBS Book, algoritm A2.2 10 | 11 | ! Description of Arguments 12 | ! Input 13 | ! t - Real, Vector of knots. Size (nctl + k) 14 | ! nctl - Integer, number of knots 15 | ! k - Integer, order of B-spline 16 | ! u - Real, location for evaluation of basis 17 | ! ind - Integer, position in knot vector such that t(ind) <= x 18 | ! 19 | ! Ouput 20 | ! B - Real, Vector, The k basis vector values 21 | use precision 22 | implicit none 23 | 24 | ! Input 25 | integer, intent(in) :: nctl, k, ind 26 | real(kind=realType), intent(in) :: t(nctl + k), u 27 | 28 | ! Output 29 | real(kind=realType), intent(out) :: B(0:k - 1) 30 | 31 | ! Working 32 | real(kind=realType) :: left(0:k - 1), right(0:k - 1), temp, saved 33 | integer :: j, r, p 34 | 35 | ! To be consistent with algorithm in The NURBS Book we will use 36 | ! zero-based ordering here 37 | B(0) = 1.0 38 | p = k - 1 39 | 40 | do j = 1, p 41 | left(j) = u - t(ind + 1 - j) 42 | right(j) = t(ind + j) - u 43 | saved = 0.0 44 | 45 | do r = 0, j - 1 46 | temp = B(r) / (right(r + 1) + left(j - r)) 47 | B(r) = saved + right(r + 1) * temp 48 | saved = left(j - r) * temp 49 | end do 50 | 51 | B(j) = saved 52 | end do 53 | 54 | end subroutine basis 55 | 56 | subroutine derivBasis(t, nctl, ku, u, ind, n, Bd) 57 | 58 | !***DESCRIPTION 59 | ! 60 | ! Written by Gaetan Kenway 61 | ! 62 | ! Abstract: derivBasis evaluates the nonzero basis functions and 63 | ! their derivatives. Algorithm adapted from The NURBS 64 | ! Book, Algorithm A2.3 65 | 66 | ! Description of Arguments 67 | ! Input 68 | ! t - Real, size(nctl + k) B-spline knot vector 69 | ! nctl - Integer, number of control points 70 | ! ku - Integer, order of B-spline 71 | ! u - Real, location for basis function evaluations 72 | ! ind - Integer, result fro findSpan 73 | ! n - Integer, order of derivates to evaluate 74 | ! 75 | ! Ouput 76 | ! Bd - Real, size(k,k) Basis functions and their derivatives 77 | 78 | use precision 79 | implicit none 80 | 81 | ! Input 82 | integer, intent(in) :: nctl, ku, ind, n 83 | real(kind=realType), intent(in) :: t(nctl + ku), u 84 | 85 | ! Output 86 | real(kind=realType), intent(out) :: Bd(0:n, 0:n) 87 | 88 | ! Working 89 | real(kind=realType) :: left(0:ku - 1), right(0:ku - 1), saved 90 | real(kind=realType) :: a(0:1, 0:ku - 1), d, temp, ndu(0:ku - 1, 0:ku - 1) 91 | integer :: j, k, r, rk, pk, s1, s2, j1, j2, p 92 | 93 | ! To be consistent with algorithm in The NURBS Book we will use 94 | ! zero-based ordering here 95 | ndu(0, 0) = 1.0 96 | 97 | ! Define degree as k-1...easier 98 | p = ku - 1 99 | do j = 1, p 100 | left(j) = u - t(ind + 1 - j) 101 | right(j) = t(ind + j) - u 102 | saved = 0.0 103 | 104 | do r = 0, j - 1 105 | ndu(j, r) = right(r + 1) + left(j - r) 106 | temp = ndu(r, j - 1) / ndu(j, r) 107 | 108 | ndu(r, j) = saved + right(r + 1) * temp 109 | saved = left(j - r) * temp 110 | end do 111 | 112 | ndu(j, j) = saved 113 | end do 114 | 115 | ! Load the basis functions 116 | do j = 0, p 117 | Bd(0, j) = ndu(j, p) 118 | end do 119 | 120 | ! This section computes the derivatives (Eq. [2.9]) 121 | do r = 0, p 122 | s1 = 0 ! Alternate rows in array a 123 | s2 = 1 124 | a(0, 0) = 1.0 125 | 126 | ! Loop to compute kth derivative 127 | do k = 1, n 128 | d = 0.0 129 | rk = r - k 130 | pk = p - k 131 | 132 | if (r >= k) then 133 | a(s2, 0) = a(s1, 0) / ndu(pk + 1, rk) 134 | d = a(s2, 0) * ndu(rk, pk) 135 | end if 136 | 137 | if (rk >= -1) then 138 | j1 = 1 139 | else 140 | j1 = -rk 141 | end if 142 | 143 | if (r - 1 <= pk) then 144 | j2 = k - 1 145 | else 146 | j2 = p - r 147 | end if 148 | 149 | do j = j1, j2 150 | a(s2, j) = (a(s1, j) - a(s1, j - 1)) / ndu(pk + 1, rk + j) 151 | d = d + a(s2, j) * ndu(rk + j, pk) 152 | end do 153 | 154 | if (r <= pk) then 155 | a(s2, k) = -a(s1, k - 1) / ndu(pk + 1, r) 156 | d = d + a(s2, k) * ndu(r, pk) 157 | end if 158 | 159 | Bd(k, r) = d 160 | 161 | ! Switch rows 162 | j = s1 163 | s1 = s2 164 | s2 = j 165 | end do 166 | end do 167 | 168 | ! Multiply through by the correct factors (Eq 2.9) 169 | r = p 170 | do k = 1, n 171 | do j = 0, p 172 | Bd(k, j) = Bd(k, j) * r 173 | end do 174 | r = r * (p - k) 175 | end do 176 | 177 | end subroutine derivBasis 178 | 179 | subroutine basis_c(t, nctl, k, u, ind, B) 180 | 181 | !***DESCRIPTION 182 | ! 183 | ! Written by Gaetan Kenway 184 | ! 185 | ! Abstract: basis evaluates the standard b-spline basis 186 | ! functions at a location x for knot vector t. Adapted 187 | ! from The NURBS Book, algoritm A2.2 188 | 189 | ! Description of Arguments 190 | ! Input 191 | ! t - Real, Vector of knots. Size (nctl + k) 192 | ! nctl - Integer, number of knots 193 | ! k - Integer, order of B-spline 194 | ! u - Real, location for evaluation of basis 195 | ! ind - Integer, position in knot vector such that t(ind) <= x 196 | ! 197 | ! Ouput 198 | ! B - Real, Vector, The k basis vector values 199 | use precision 200 | implicit none 201 | 202 | ! Input 203 | integer, intent(in) :: nctl, k, ind 204 | real(kind=realType), intent(in) :: t(nctl + k) 205 | complex(kind=realType), intent(in) :: u 206 | 207 | ! Output 208 | complex(kind=realType), intent(out) :: B(0:k - 1) 209 | 210 | ! Working 211 | complex(kind=realType) :: left(0:k - 1), right(0:k - 1), temp, saved 212 | integer :: j, r, p 213 | 214 | ! To be consistent with algorithm in The NURBS Book we will use 215 | ! zero-based ordering here 216 | B(0) = cmplx(1.0, 0.0) 217 | p = k - 1 218 | 219 | do j = 1, p 220 | left(j) = u - t(ind + 1 - j) 221 | right(j) = t(ind + j) - u 222 | saved = 0.0 223 | 224 | do r = 0, j - 1 225 | temp = B(r) / (right(r + 1) + left(j - r)) 226 | B(r) = saved + right(r + 1) * temp 227 | saved = left(j - r) * temp 228 | end do 229 | 230 | B(j) = saved 231 | end do 232 | 233 | end subroutine basis_c 234 | -------------------------------------------------------------------------------- /src/compute_curve.f90: -------------------------------------------------------------------------------- 1 | 2 | subroutine curve_jacobian_wrap(s, sd, t, k, nctl, n, nd, vals, row_ptr, col_ind) 3 | use precision 4 | implicit none 5 | ! Input 6 | integer, intent(in) :: k, nctl, n, nd 7 | real(kind=realType), intent(in) :: t(nctl + k), s(n), sd(nd) 8 | ! Output 9 | real(kind=realType), intent(inout) :: vals((n + nd) * k) 10 | integer, intent(inout) :: row_ptr(n + nd + 1) 11 | integer, intent(inout) :: col_ind((n + nd) * k) 12 | real(kind=realType) :: basisu(k), basisud(k, k) 13 | integer :: i, j, counter, ileft 14 | 15 | counter = 1 16 | do i = 1, n ! Do the values first 17 | call findSpan(s(i), k, t, nctl, ileft) 18 | call basis(t, nctl, k, s(i), ileft, basisu) 19 | 20 | row_ptr(i) = counter - 1 21 | do j = 1, k 22 | col_ind(counter) = ileft - k + j - 1 23 | vals(counter) = basisu(j) 24 | counter = counter + 1 25 | end do 26 | end do 27 | do i = 1, nd ! Do the derivatives next 28 | call findSpan(sd(i), k, t, nctl, ileft) 29 | call derivBasis(t, nctl, k, sd(i), ileft, 1, basisud) 30 | 31 | row_ptr(i + n) = counter - 1 32 | do j = 1, k 33 | col_ind(counter) = ileft - k + j - 1 34 | vals(counter) = basisud(2, j) 35 | counter = counter + 1 36 | end do 37 | end do 38 | row_ptr(n + nd + 1) = counter - 1 39 | end subroutine curve_jacobian_wrap 40 | 41 | subroutine constr_jac(A_val, A_row_ptr, A_col_ind, B_val, B_row_ptr, B_col_ind, C_val, C_row_ptr, C_col_ind, & 42 | Am, An, Cm, Annz, Bnnz, Cnnz, J_val, J_col_ind, J_row_ptr) 43 | use precision 44 | implicit none 45 | ! Input 46 | integer, intent(in) :: Am, An, Cm, Annz, Bnnz, Cnnz 47 | real(kind=realType), intent(in) :: A_val(Annz), B_val(Bnnz), C_val(Cnnz) 48 | integer, intent(in) :: A_col_ind(Annz), B_col_ind(Bnnz), C_col_ind(Cnnz) 49 | integer, intent(in) :: A_row_ptr(Am + 1), B_row_ptr(Am + 1), C_row_ptr(Cm + 1) 50 | 51 | ! Output 52 | real(kind=realType), intent(out) :: J_val(Annz + Bnnz + Cnnz) 53 | integer, intent(out) :: J_col_ind(Annz + Bnnz + Cnnz) 54 | integer, intent(out) :: J_row_ptr(Am + Cm + 1) 55 | 56 | ! Local 57 | integer :: i, j, counter 58 | ! This functions assembes the following CSR matrix: 59 | ! J = [A B] 60 | ! [C 0] 61 | 62 | ! Now assmeble the full jacobain 63 | counter = 1 64 | J_row_ptr(1) = 0 65 | do i = 1, Am 66 | do j = 1, A_row_ptr(i + 1) - A_row_ptr(i) 67 | J_val(counter) = A_val(A_row_ptr(i) + j) 68 | J_col_ind(counter) = A_col_ind(A_row_ptr(i) + j) 69 | counter = counter + 1 70 | end do 71 | do j = 1, B_row_ptr(i + 1) - B_row_ptr(i) 72 | J_val(counter) = B_val(B_row_ptr(i) + j) 73 | J_col_ind(counter) = B_col_ind(B_row_ptr(i) + j) + An 74 | counter = counter + 1 75 | end do 76 | J_row_ptr(i + 1) = counter - 1 77 | end do 78 | do i = 1, Cm 79 | do j = 1, C_row_ptr(i + 1) - C_row_ptr(i) 80 | J_val(counter) = C_val(C_row_ptr(i) + j) 81 | J_col_ind(counter) = C_col_ind(C_row_ptr(i) + j) 82 | counter = counter + 1 83 | end do 84 | J_row_ptr(i + 1 + am) = counter - 1 85 | end do 86 | end subroutine constr_jac 87 | 88 | subroutine poly_length(X, n, ndim, length) 89 | ! Compute the length of the spatial polygon 90 | use precision 91 | implicit none 92 | 93 | !Input 94 | integer, intent(in) :: n, ndim 95 | real(kind=realType), intent(in) :: X(ndim, n) 96 | 97 | ! Ouput 98 | real(kind=realType), intent(out) :: length 99 | 100 | ! Working 101 | integer :: i, idim 102 | real(kind=realType) :: dist 103 | 104 | length = 0.0 105 | do i = 1, n - 1 106 | dist = 0.0 107 | do idim = 1, ndim 108 | dist = dist + (X(idim, i) - X(idim, i + 1))**2 109 | end do 110 | length = length + sqrt(dist) 111 | end do 112 | 113 | end subroutine poly_length 114 | 115 | subroutine curve_para_corr(t, k, s, coef, nctl, ndim, length, n, X) 116 | 117 | ! Do Hoschek parameter correction 118 | use precision 119 | implicit none 120 | ! Input/Output 121 | integer, intent(in) :: k, nctl, ndim, n 122 | real(kind=realType), intent(in) :: t(nctl + k) 123 | real(kind=realType), intent(inout) :: s(n) 124 | real(kind=realType), intent(in) :: coef(ndim, nctl) 125 | real(kind=realType), intent(in) :: X(ndim, n) 126 | real(kind=realType), intent(in) :: length 127 | ! Working 128 | integer :: i, j, max_inner_iter 129 | real(kind=realType) :: D(ndim), D2(ndim) 130 | real(kind=realType) :: val(ndim), deriv(ndim) 131 | real(kind=realType) :: c, s_tilde 132 | 133 | max_inner_iter = 10 134 | do i = 2, n - 1 135 | call eval_curve(s(i), t, k, coef, nctl, ndim, 1, val) 136 | call eval_curve_deriv(s(i), t, k, coef, nctl, ndim, deriv) 137 | 138 | D = X(:, i) - val 139 | c = dot_product(D, deriv) / NORM2(deriv) 140 | 141 | inner_loop: do j = 1, max_inner_iter 142 | 143 | s_tilde = s(i) + c * (t(nctl + k) - t(1)) / length 144 | call eval_curve(s_tilde, t, k, coef, nctl, ndim, 1, val) 145 | D2 = X(:, i) - val 146 | if (NORM2(D) .ge. NORM2(D2)) then 147 | s(i) = s_tilde 148 | exit inner_loop 149 | else 150 | c = c * 0.5 151 | end if 152 | end do inner_loop 153 | end do 154 | 155 | end subroutine curve_para_corr 156 | 157 | function compute_rms_curve(t, k, s, coef, nctl, ndim, n, X) 158 | ! Compute the rms 159 | use precision 160 | implicit none 161 | ! Input/Output 162 | integer, intent(in) :: k, nctl, ndim, n 163 | real(kind=realType), intent(in) :: t(k + nctl) 164 | real(kind=realType), intent(in) :: s(n) 165 | real(kind=realType), intent(in) :: coef(ndim, nctl) 166 | real(kind=realType), intent(in) :: X(ndim, n) 167 | real(kind=realType) :: compute_rms_curve 168 | 169 | ! Working 170 | integer :: i, idim 171 | real(kind=realType) :: val(ndim), D(ndim) 172 | 173 | compute_rms_curve = 0.0 174 | do i = 1, n 175 | call eval_curve(s(i), t, k, coef, nctl, ndim, 1, val) 176 | D = val - X(:, i) 177 | do idim = 1, ndim 178 | compute_rms_curve = compute_rms_curve + D(idim)**2 179 | end do 180 | end do 181 | compute_rms_curve = sqrt(compute_rms_curve / n) 182 | end function compute_rms_curve 183 | -------------------------------------------------------------------------------- /src/compute_surface.f90: -------------------------------------------------------------------------------- 1 | subroutine surface_jacobian_wrap(u, v, tu, tv, ku, kv, nctlu, nctlv, nu, nv, vals, & 2 | row_ptr, col_ind) 3 | 4 | use precision 5 | implicit none 6 | 7 | ! Input 8 | integer, intent(in) :: ku, kv, nctlu, nctlv, nu, nv 9 | real(kind=realType), intent(in) :: u(nv, nu), v(nv, nu) 10 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv) 11 | 12 | ! Output 13 | real(kind=realType), intent(out) :: vals(nu * nv * ku * kv) 14 | integer, intent(out) :: col_ind(nu * nv * ku * kv), row_ptr(nu * nv + 1) 15 | 16 | ! Working 17 | real(kind=realType) :: basisu(ku), basisv(kv) 18 | integer :: ileftu, ileftv 19 | integer :: i, j, ii, jj, counter 20 | 21 | counter = 1 22 | do i = 1, nu 23 | do j = 1, nv 24 | ! Get u interval 25 | call findSpan(u(j, i), ku, tu, nctlu, ileftu) 26 | call basis(tu, nctlu, ku, u(j, i), ileftu, basisu) 27 | 28 | ! Get v interval 29 | call findSpan(v(j, i), kv, tv, nctlv, ileftv) 30 | call basis(tv, nctlv, kv, v(j, i), ileftv, basisv) 31 | 32 | row_ptr((i - 1) * nv + j) = counter - 1 33 | do ii = 1, ku 34 | do jj = 1, kv 35 | col_ind(counter) = (ileftu - ku + ii - 1) * Nctlv + (ileftv - kv + jj - 1) 36 | vals(counter) = basisu(ii) * basisv(jj) 37 | counter = counter + 1 38 | 39 | end do 40 | end do 41 | end do 42 | end do 43 | row_ptr(nu * nv + 1) = counter - 1 44 | 45 | end subroutine surface_jacobian_wrap 46 | 47 | subroutine surface_para_corr(tu, tv, ku, kv, u, v, coef, nctlu, nctlv, ndim, nu, nv, X, rms) 48 | 49 | ! Do Hoschek parameter correction 50 | use precision 51 | implicit none 52 | 53 | ! Input/Output 54 | integer, intent(in) :: ku, kv, nctlu, nctlv, ndim, nu, nv 55 | real(kind=realType), intent(in) :: tu(ku + nctlu), tv(kv + nctlv) 56 | real(kind=realType), intent(inout) :: u(nv, nu), v(nv, nu) 57 | real(kind=realType), intent(in) :: coef(ndim, nctlv, nctlu) 58 | real(kind=realType), intent(in) :: X(ndim, nv, nu) 59 | real(kind=realType), intent(out) :: rms 60 | 61 | ! Working 62 | integer :: i, j, jj, max_inner_iter 63 | real(kind=realType) :: D(ndim), D2(ndim) 64 | real(kind=realType) :: val(ndim), deriv(ndim, 2), deriv2(ndim, 2, 2) 65 | real(kind=realType) :: u_tilde, v_tilde 66 | real(kind=realType) :: A(2, 2), ki(2), delta(2) 67 | 68 | max_inner_iter = 10 69 | rms = 0.0 70 | 71 | do i = 2, nu - 1 72 | do j = 2, nv - 2 73 | call eval_surface(u(j, i), v(j, i), tu, tv, ku, kv, coef, nctlu, nctlv, ndim, val) 74 | call eval_surface_deriv(u(j, i), v(j, i), tu, tv, ku, kv, coef, nctlu, nctlv, ndim, deriv) 75 | call eval_surface_deriv2(u(j, i), v(j, i), tu, tv, ku, kv, coef, nctlu, nctlv, ndim, deriv2) 76 | 77 | D = val - X(:, j, i) 78 | 79 | A(1, 1) = NORM2(deriv(:, i))**2 + dot_product(D, deriv2(:, 1, 1)) 80 | A(1, 2) = dot_product(deriv(:, 1), deriv(:, 2)) + dot_product(D, deriv2(:, 1, 2)) 81 | A(2, 1) = A(1, 2) 82 | A(2, 2) = NORM2(deriv(:, 2))**2 + dot_product(D, deriv2(:, 2, 2)) 83 | 84 | ki(1) = -dot_product(D, deriv(:, 1)) 85 | ki(2) = -dot_product(D, deriv(:, 2)) 86 | 87 | call solve_2by2(A, ki, delta) 88 | 89 | if (j .eq. 1 .or. j .eq. nv) then 90 | delta(1) = 0.0 91 | end if 92 | if (i .eq. 1 .or. i .eq. nu) then 93 | delta(2) = 0.0 94 | end if 95 | inner_loop: do jj = 1, max_inner_iter 96 | u_tilde = u(j, i) + delta(1) 97 | v_tilde = v(j, i) + delta(2) 98 | 99 | call eval_surface(u_tilde, v_tilde, tu, tv, ku, kv, coef, nctlu, nctlv, ndim, val) 100 | D2 = val - X(i, j, :) 101 | if (NORM2(D) .ge. NORM2(D2)) then 102 | u(j, i) = u_tilde 103 | v(j, i) = v_tilde 104 | exit inner_loop 105 | else 106 | delta = delta * 0.5 107 | end if 108 | end do inner_loop 109 | end do 110 | end do 111 | 112 | ! Lets redo the full RMS 113 | rms = 0.0 114 | 115 | do i = 1, nu 116 | do j = 1, nv 117 | call eval_surface(u(j, i), v(j, i), tu, tv, ku, kv, coef, nctlu, nctlv, ndim, val) 118 | D = X(i, j, :) - val 119 | rms = rms + dot_product(D, D) 120 | end do 121 | end do 122 | rms = sqrt(rms / (nu * nv)) 123 | 124 | end subroutine surface_para_corr 125 | 126 | function compute_rms_surface(tu, tv, ku, kv, u, v, coef, nctlu, nctlv, ndim, nu, nv, X) 127 | ! Do Hoschek parameter correction 128 | use precision 129 | implicit none 130 | 131 | ! Input/Output 132 | integer, intent(in) :: ku, kv, nctlu, nctlv, ndim, nu, nv 133 | real(kind=realType), intent(in) :: tu(ku + nctlu), tv(kv + nctlv) 134 | real(kind=realType), intent(inout) :: u(nv, nu), v(nv, nu) 135 | real(kind=realType), intent(in) :: coef(ndim, nctlv, nctlu) 136 | real(kind=realType), intent(in) :: X(ndim, nv, nu) 137 | 138 | ! Working 139 | integer :: i, j, idim 140 | real(kind=realType) :: val(ndim), D(ndim) 141 | real(kind=realType) :: compute_rms_surface 142 | 143 | compute_rms_surface = 0.0 144 | do i = 1, nu 145 | do j = 1, nv 146 | call eval_surface(u(j, i), v(j, i), tu, tv, ku, kv, coef, nctlu, nctlv, ndim, val) 147 | D = val - X(:, j, i) 148 | do idim = 1, ndim 149 | compute_rms_surface = compute_rms_surface + D(idim)**2 150 | end do 151 | end do 152 | end do 153 | compute_rms_surface = sqrt(compute_rms_surface / (nu * nv)) 154 | 155 | end function compute_rms_surface 156 | 157 | -------------------------------------------------------------------------------- /src/compute_volume.f90: -------------------------------------------------------------------------------- 1 | subroutine volume_jacobian_wrap(u, v, w, tu, tv, tw, ku, kv, kw, nctlu, nctlv, nctlw, & 2 | nu, nv, nw, vals, row_ptr, col_ind) 3 | use precision 4 | implicit none 5 | 6 | ! Input 7 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw, nu, nv, nw 8 | real(kind=realType), intent(in) :: u(nw, nv, nu), v(nw, nv, nu), w(nw, nv, nu) 9 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 10 | 11 | ! Output 12 | real(kind=realType), intent(out) :: vals(nu * nv * nw * ku * kv * kw) 13 | integer, intent(out) :: col_ind(nu * nv * nw * ku * kv * kw), row_ptr(nu * nv * nw + 1) 14 | 15 | ! Working 16 | real(kind=realType) :: basisu(ku), basisv(kv), basisw(kw) 17 | integer :: i, j, k, ii, jj, kk, counter, c1, c2 18 | integer :: ileftu, ileftv, ileftw 19 | 20 | counter = 1 21 | do i = 1, nu 22 | do j = 1, nv 23 | do k = 1, nw 24 | ! U 25 | call findSpan(u(k, j, i), ku, tu, nctlu, ileftu) 26 | call basis(tu, nctlu, ku, u(k, j, i), ileftu, basisu) 27 | 28 | ! V 29 | call findSpan(v(k, j, i), kv, tv, nctlv, ileftv) 30 | call basis(tv, nctlv, kv, v(k, j, i), ileftv, basisv) 31 | 32 | ! W 33 | call findSpan(w(k, j, i), kw, tw, nctlw, ileftw) 34 | call basis(tw, nctlw, kw, w(k, j, i), ileftw, basisw) 35 | 36 | row_ptr((i - 1) * nv * nw + (j - 1) * nw + k) = counter - 1 37 | do ii = 1, ku 38 | c1 = (ileftu - ku + ii - 1) * Nctlv * Nctlw 39 | do jj = 1, kv 40 | c2 = (ileftv - kv + jj - 1) * Nctlw 41 | do kk = 1, kw 42 | col_ind(counter) = c1 + c2 + (ileftw - kw + kk - 1) 43 | vals(counter) = basisu(ii) * basisv(jj) * basisw(kk) 44 | counter = counter + 1 45 | end do 46 | end do 47 | end do 48 | end do 49 | end do 50 | end do 51 | row_ptr(nu * nv * nw + 1) = counter - 1 52 | 53 | end subroutine volume_jacobian_wrap 54 | -------------------------------------------------------------------------------- /src/eval_curve.f90: -------------------------------------------------------------------------------- 1 | subroutine eval_curve(s, t, k, coef, nctl, ndim, n, val) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract eval_surf is a vector version of the B-spline evaluation function 8 | ! 9 | ! Description of Arguments 10 | ! Input 11 | ! s - Real, Vector of s coordinates, length n 12 | ! t - Real, Knot vector. Length nctl+k 13 | ! k - Integer, order of B-spline 14 | ! coef - Real, Array of b-sline coefficients Size (ndim, nctl) 15 | ! nctl - Integer, Number of control points 16 | ! 17 | ! Ouput 18 | ! val - Real, Evaluated points, size ndim by n 19 | 20 | use precision 21 | implicit none 22 | ! Input 23 | integer, intent(in) :: k, nctl, ndim, n 24 | real(kind=realType), intent(in) :: s(n) 25 | real(kind=realType), intent(in) :: t(nctl + k) 26 | real(kind=realType), intent(in) :: coef(ndim, nctl) 27 | 28 | ! Output 29 | real(kind=realType), intent(out) :: val(ndim, n) 30 | 31 | ! Working 32 | integer :: i, l, idim, istart, ileft 33 | real(kind=realType) :: basisu(k) 34 | 35 | val(:, :) = 0.0 36 | do i = 1, n 37 | call findSpan(s(i), k, t, nctl, ileft) 38 | call basis(t, nctl, k, s(i), ileft, basisu) 39 | istart = ileft - k 40 | do l = 1, k 41 | do idim = 1, ndim 42 | val(idim, i) = val(idim, i) + basisu(l) * coef(idim, istart + l) 43 | end do 44 | end do 45 | end do 46 | end subroutine eval_curve 47 | 48 | subroutine eval_curve_deriv(s, t, k, coef, nctl, ndim, val) 49 | 50 | !***DESCRIPTION 51 | ! 52 | ! Written by Gaetan Kenway 53 | ! 54 | ! Abstract eval_surf_deriv is a scalar version of the 55 | ! B-spline derivative evaluation function 56 | ! 57 | ! Description of Arguments 58 | ! Input 59 | ! s - Real, s coordinate 60 | ! t - Real, Knot vector. Length nctl+k 61 | ! k - Integer, order of B-spline 62 | ! coef - Real, Array of B-spline coefficients. Size (ndim, nctl) 63 | ! nctl - Integer, Number of control points 64 | ! 65 | ! Ouput 66 | ! val - Real, Evaluated point, size ndim 67 | 68 | use precision 69 | implicit none 70 | 71 | ! Input 72 | integer, intent(in) :: k, nctl, ndim 73 | real(kind=realType), intent(in) :: s 74 | real(kind=realType), intent(in) :: t(nctl + k) 75 | real(kind=realType), intent(in) :: coef(ndim, nctl) 76 | 77 | ! Output 78 | real(kind=realType), intent(out) :: val(ndim) 79 | 80 | ! Working 81 | integer :: idim 82 | 83 | ! Functions 84 | real(kind=realType) :: bvalu 85 | 86 | do idim = 1, ndim 87 | val(idim) = bvalu(t, coef(idim, :), nctl, k, 1, s) 88 | end do 89 | 90 | end subroutine eval_curve_deriv 91 | 92 | subroutine eval_curve_deriv2(s, t, k, coef, nctl, ndim, val) 93 | 94 | !***DESCRIPTION 95 | ! 96 | ! Written by Gaetan Kenway 97 | ! 98 | ! Abstract eval_curve_deriv2 evals the 2nd derivative 99 | ! B-spline derivative evaluation function 100 | ! 101 | ! Description of Arguments 102 | ! Input 103 | ! s - Real, s coordinate 104 | ! t - Real, Knot vector. Length nctl+k 105 | ! k - Integer, order of B-spline 106 | ! coef - Real, Array of B-spline coefficients Size (ndim, nctl) 107 | ! nctl - Integer, Number of control points 108 | ! 109 | ! Ouput 110 | ! val - Real, Evaluated point, size ndim 111 | 112 | use precision 113 | implicit none 114 | ! Input 115 | integer, intent(in) :: k, nctl, ndim 116 | real(kind=realType), intent(in) :: s 117 | real(kind=realType), intent(in) :: t(nctl + k) 118 | real(kind=realType), intent(in) :: coef(ndim, nctl) 119 | 120 | ! Output 121 | real(kind=realType), intent(out) :: val(ndim) 122 | 123 | ! Working 124 | integer :: idim 125 | 126 | ! Functions 127 | real(kind=realType) :: bvalu 128 | 129 | if (k == 2) then 130 | val(:) = 0.0 131 | else 132 | do idim = 1, ndim 133 | val(idim) = bvalu(t, coef(idim, :), nctl, k, 2, s) 134 | end do 135 | end if 136 | 137 | end subroutine eval_curve_deriv2 138 | 139 | subroutine eval_curve_c(s, t, k, coef, nctl, ndim, n, val) 140 | 141 | !***DESCRIPTION 142 | ! 143 | ! Written by Gaetan Kenway 144 | ! 145 | ! Abstract eval_curve_complex is a special version for evaluation 146 | ! of data when control points are used in a complex-step analysis 147 | ! The actual derivative is computed analytically, but the output looks 148 | ! like the CS went all the way through 149 | ! 150 | ! Description of Arguments 151 | ! Input 152 | ! s - Real, s coordinate 153 | ! t - Real, Knot vector. Length nctl+k 154 | ! k - Integer, order of B-spline 155 | ! coef - Real, Array of B-spline coefficients Size (ndim, nctl) 156 | ! nctl - Integer, Number of control points 157 | ! 158 | ! Ouput 159 | ! val - Real, Evaluated point, size ndim 160 | 161 | use precision 162 | implicit none 163 | ! Input 164 | integer, intent(in) :: k, nctl, ndim, n 165 | complex(kind=realType), intent(in) :: s(n) 166 | real(kind=realType), intent(in) :: t(nctl + k) 167 | complex(kind=realType), intent(in) :: coef(ndim, nctl) 168 | 169 | ! Output 170 | complex(kind=realType), intent(out) :: val(ndim, n) 171 | 172 | ! Working 173 | integer :: i, l, istart, ileft, idim 174 | complex(kind=realType) :: basisu(k) 175 | 176 | val(:, :) = cmplx(0.0, 0.0) 177 | do i = 1, n 178 | call findSpan(real(s(i)), k, t, nctl, ileft) 179 | call basis_c(t, nctl, k, s(i), ileft, basisu) 180 | 181 | istart = ileft - k 182 | do l = 1, k 183 | do idim = 1, ndim 184 | val(idim, i) = val(idim, i) + basisu(l) * coef(idim, istart + l) 185 | end do 186 | end do 187 | end do 188 | end subroutine eval_curve_c 189 | 190 | subroutine eval_curve_deriv_c(s, t, k, coef, nctl, ndim, val) 191 | 192 | !***DESCRIPTION 193 | ! 194 | ! Written by Gaetan Kenway 195 | ! 196 | ! Abstract eval_surf_deriv is a scalar version of the 197 | ! B-spline derivative evaluation function 198 | ! 199 | ! Description of Arguments 200 | ! Input 201 | ! s - Real, s coordinate 202 | ! t - Real, Knot vector. Length nctl+k 203 | ! k - Integer, order of B-spline 204 | ! coef - Complex, Array of B-spline coefficients. Size (ndim, nctl) 205 | ! nctl - Integer, Number of control points 206 | ! 207 | ! Ouput 208 | ! val - Complex, Evaluated derivative, size ndim 209 | 210 | use precision 211 | implicit none 212 | ! Input 213 | integer, intent(in) :: k, nctl, ndim 214 | real(kind=realType), intent(in) :: s 215 | real(kind=realType), intent(in) :: t(nctl + k) 216 | complex(kind=realType), intent(in) :: coef(ndim, nctl) 217 | 218 | ! Output 219 | complex(kind=realType), intent(out) :: val(ndim) 220 | 221 | ! Working 222 | integer :: idim 223 | 224 | ! Functions 225 | complex(kind=realType) :: cbvalu 226 | 227 | do idim = 1, ndim 228 | val(idim) = cbvalu(t, coef(idim, :), nctl, k, 1, s) 229 | end do 230 | 231 | end subroutine eval_curve_deriv_c 232 | 233 | subroutine eval_curve_deriv2_c(s, t, k, coef, nctl, ndim, val) 234 | 235 | !***DESCRIPTION 236 | ! 237 | ! Written by Gaetan Kenway 238 | ! 239 | ! Abstract eval_curve_deriv2 evals the 2nd derivative 240 | ! B-spline derivative evaluation function 241 | ! 242 | ! Description of Arguments 243 | ! Input 244 | ! s - Real, s coordinate 245 | ! t - Real, Knot vector. Length nctl+k 246 | ! k - Integer, order of B-spline 247 | ! coef - Complex, Array of B-spline coefficients Size (ndim, nctl) 248 | ! nctl - Integer, Number of control points 249 | ! 250 | ! Ouput 251 | ! val - Real, Evaluated point, size ndim 252 | 253 | use precision 254 | implicit none 255 | ! Input 256 | integer, intent(in) :: k, nctl, ndim 257 | real(kind=realType), intent(in) :: s 258 | real(kind=realType), intent(in) :: t(nctl + k) 259 | complex(kind=realType), intent(in) :: coef(ndim, nctl) 260 | 261 | ! Output 262 | complex(kind=realType), intent(out) :: val(ndim) 263 | 264 | ! Working 265 | integer :: idim 266 | 267 | ! Functions 268 | complex(kind=realType) :: cbvalu 269 | 270 | do idim = 1, ndim 271 | val(idim) = cbvalu(t, coef(idim, :), nctl, k, 2, s) 272 | end do 273 | 274 | end subroutine eval_curve_deriv2_c 275 | -------------------------------------------------------------------------------- /src/eval_surface.f90: -------------------------------------------------------------------------------- 1 | subroutine eval_surface(u, v, tu, tv, ku, kv, coef, nctlu, nctlv, ndim, & 2 | n, m, val) 3 | 4 | !***DESCRIPTION 5 | ! 6 | ! Written by Gaetan Kenway 7 | ! 8 | ! Abstract eval_surface evaluates (possibly) many points on the surface 9 | ! 10 | ! Description of Arguments 11 | ! Input 12 | ! u - Real, u coordinate, size(m, n) 13 | ! v - Real, v coordinate, size(m, n) 14 | ! tu - Real, Knot vector in u. size(nctlu+ku) 15 | ! tv - Real, Knot vector in v. size(nctlv+kv) 16 | ! ku - Integer, order of B-spline in u 17 | ! kv - Integer, order of B-spline in v 18 | ! coef - Real, Array of B-spline coefficients Size (ndim, nctlv, nctlu) 19 | ! nctlu - Integer, Number of control points in u 20 | ! nctlv - Integer, Number of control points in v 21 | ! ndim - Integer, Spatial Dimension 22 | ! 23 | ! Ouput 24 | ! val - Real, Evaluated point(s), size (ndim, m, n) 25 | 26 | use precision 27 | implicit none 28 | 29 | ! Input 30 | integer, intent(in) :: ku, kv, nctlu, nctlv, ndim, n, m 31 | real(kind=realType), intent(in) :: u(m, n), v(m, n) 32 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv) 33 | real(kind=realType), intent(in) :: coef(ndim, nctlv, nctlu) 34 | 35 | ! Output 36 | real(kind=realType), intent(out) :: val(ndim, m, n) 37 | 38 | ! Working 39 | integer :: idim, istartu, istartv, i, j, ii, jj 40 | integer :: ileftu, ileftv 41 | real(kind=realType) :: basisu(ku), basisv(kv) 42 | 43 | val(:, :, :) = 0.0 44 | do ii = 1, n 45 | do jj = 1, m 46 | ! U 47 | call findSpan(u(jj, ii), ku, tu, nctlu, ileftu) 48 | call basis(tu, nctlu, ku, u(jj, ii), ileftu, basisu) 49 | istartu = ileftu - ku 50 | 51 | ! V 52 | call findSpan(v(jj, ii), kv, tv, nctlv, ileftv) 53 | call basis(tv, nctlv, kv, v(jj, ii), ileftv, basisv) 54 | istartv = ileftv - kv 55 | 56 | do i = 1, ku 57 | do j = 1, kv 58 | do idim = 1, ndim 59 | val(idim, jj, ii) = val(idim, jj, ii) + basisu(i) & 60 | * basisv(j) * coef(idim, istartv + j, istartu + i) 61 | end do 62 | end do 63 | end do 64 | end do 65 | end do 66 | 67 | end subroutine eval_surface 68 | 69 | subroutine eval_surface_deriv(u, v, tu, tv, ku, kv, coef, nctlu, nctlv, & 70 | ndim, val) 71 | 72 | !***DESCRIPTION 73 | ! 74 | ! Written by Gaetan Kenway 75 | ! 76 | ! Abstract eval_surface_deriv evaluates the derivative of a 77 | ! point on the surface 78 | ! 79 | ! Description of Arguments 80 | ! Input 81 | ! u - Real, u coordinate 82 | ! v - Real, v coordinate 83 | ! tu - Real, Knot vector in u. size(nctlu+ku) 84 | ! tv - Real, Knot vector in v. size(nctlv+kv) 85 | ! ku - Integer, order of B-spline in u 86 | ! kv - Integer, order of B-spline in v 87 | ! coef - Real, Array of B-spline coefficients Size (ndim, nctlv, nctlu) 88 | ! nctlu - Integer, Number of control points in u 89 | ! nctlv - Integer, Number of control points in v 90 | ! ndim - Integer, Spatial Dimension 91 | ! 92 | ! Ouput 93 | ! val - Real, Evaluated derivatives, size (ndim, 2) 94 | 95 | use precision 96 | implicit none 97 | 98 | ! Input 99 | integer, intent(in) :: ku, kv, nctlu, nctlv, ndim 100 | real(kind=realType), intent(in) :: u, v 101 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv) 102 | real(kind=realType), intent(in) :: coef(ndim, nctlv, nctlu) 103 | 104 | ! Output 105 | real(kind=realType), intent(out) :: val(ndim, 2) 106 | 107 | ! Working 108 | integer :: idim 109 | real(kind=realType) :: b2val 110 | 111 | do idim = 1, ndim 112 | val(idim, 1) = b2val(v, u, 0, 1, tv, tu, nctlv, nctlu, kv, ku, coef(idim, :, :)) 113 | val(idim, 2) = b2val(v, u, 1, 0, tv, tu, nctlv, nctlu, kv, ku, coef(idim, :, :)) 114 | end do 115 | 116 | end subroutine eval_surface_deriv 117 | 118 | subroutine eval_surface_deriv2(u, v, tu, tv, ku, kv, coef, nctlu, nctlv, ndim, val) 119 | 120 | !***DESCRIPTION 121 | ! 122 | ! Written by Gaetan Kenway 123 | ! 124 | ! Abstract eval_surface_deriv2 evaluates the second derivative 125 | ! of a point on the surface 126 | ! 127 | ! Description of Arguments 128 | ! Input 129 | ! u - Real, u coordinate 130 | ! v - Real, v coordinate 131 | ! tu - Real, Knot vector in u. size(nctlu+ku) 132 | ! tv - Real, Knot vector in v. size(nctlv+kv) 133 | ! ku - Integer, order of B-spline in u 134 | ! kv - Integer, order of B-spline in v 135 | ! coef - Real, Array of B-spline coefficients Size (ndim, nctlv, nctlu) 136 | ! nctlu - Integer, Number of control points in u 137 | ! nctlv - Integer, Number of control points in v 138 | ! ndim - Integer, Spatial Dimension 139 | ! 140 | ! Ouput 141 | ! val - Real, Evaluated second derivatives, size (ndim, 2, 2) 142 | 143 | use precision 144 | implicit none 145 | 146 | ! Input 147 | integer, intent(in) :: ku, kv, nctlu, nctlv, ndim 148 | real(kind=realType), intent(in) :: u, v 149 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv) 150 | real(kind=realType), intent(in) :: coef(ndim, nctlv, nctlu) 151 | 152 | ! Output 153 | real(kind=realType), intent(out) :: val(ndim, 2, 2) 154 | 155 | ! Working 156 | integer :: idim 157 | real(kind=realType) :: b2val 158 | 159 | do idim = 1, ndim 160 | val(idim, 1, 1) = b2val(v, u, 0, 2, tv, tu, nctlv, nctlu, kv, ku, coef(idim, :, :)) 161 | val(idim, 1, 2) = b2val(v, u, 1, 1, tv, tu, nctlv, nctlu, kv, ku, coef(idim, :, :)) 162 | val(idim, 2, 1) = val(idim, 1, 2) 163 | val(idim, 2, 2) = b2val(v, u, 2, 0, tv, tu, nctlv, nctlu, kv, ku, coef(idim, :, :)) 164 | end do 165 | 166 | end subroutine eval_surface_deriv2 167 | -------------------------------------------------------------------------------- /src/eval_volume.f90: -------------------------------------------------------------------------------- 1 | subroutine eval_volume(u, v, w, tu, tv, tw, ku, kv, kw, coef, & 2 | nctlu, nctlv, nctlw, ndim, n, m, l, val) 3 | 4 | !***DESCRIPTION 5 | ! 6 | ! Written by Gaetan Kenway 7 | ! 8 | ! Abstract eval_volume evaluates (possibly) many points on the 9 | ! b-spline volume 10 | ! 11 | ! Description of Arguments 12 | ! Input 13 | ! u - Real, u coordinate, size(l, m, n) 14 | ! v - Real, v coordinate, size(l, m, n) 15 | ! w - Real, w coordinate, size(l, m, n) 16 | ! tu - Real, Knot vector in u. Length nctlu+ku 17 | ! tv - Real, Knot vector in v. Length nctlv+kv 18 | ! tw - Real, Knot vector in w. Length nctlv+kw 19 | ! ku - Integer, order of B-spline in u 20 | ! kv - Integer, order of B-spline in v 21 | ! kw - Integer, order of B-spline in w 22 | ! coef - Real, Array of B-spline coefficients 23 | ! Size (ndim, nctlw, nctlv, nctlu) 24 | ! nctlu - Integer, Number of control points in u 25 | ! nctlv - Integer, Number of control points in v 26 | ! nctlw - Integer, Number of control points in w 27 | ! ndim - Integer, Spatial Dimension 28 | ! 29 | ! Ouput 30 | ! val - Real, Evaluated points, size (ndim, l, m, n) 31 | 32 | use precision 33 | implicit none 34 | 35 | ! Input 36 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw 37 | integer, intent(in) :: ndim, n, m, l 38 | real(kind=realType), intent(in) :: u(l, m, n), v(l, m, n), w(l, m, n) 39 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 40 | real(kind=realType), intent(in) :: coef(ndim, nctlw, nctlv, nctlu) 41 | 42 | ! Output 43 | real(kind=realType), intent(out) :: val(ndim, l, m, n) 44 | 45 | ! Working 46 | integer :: idim, istartu, istartv, istartw 47 | integer :: i, j, k, ii, jj, kk 48 | integer :: ileftu, ileftv, ileftw 49 | real(kind=realType) :: basisu(ku), basisv(kv), basisw(kw) 50 | 51 | val(:, :, :, :) = 0.0 52 | do ii = 1, n 53 | do jj = 1, m 54 | do kk = 1, l 55 | ! U 56 | call findSpan(u(kk, jj, ii), ku, tu, nctlu, ileftu) 57 | call basis(tu, nctlu, ku, u(kk, jj, ii), ileftu, basisu) 58 | istartu = ileftu - ku 59 | 60 | ! V 61 | call findSpan(v(kk, jj, ii), kv, tv, nctlv, ileftv) 62 | call basis(tv, nctlv, kv, v(kk, jj, ii), ileftv, basisv) 63 | istartv = ileftv - kv 64 | 65 | ! W 66 | call findSpan(w(kk, jj, ii), kw, tw, nctlw, ileftw) 67 | call basis(tw, nctlw, kw, w(kk, jj, ii), ileftw, basisw) 68 | istartw = ileftw - kw 69 | 70 | do i = 1, ku 71 | do j = 1, kv 72 | do k = 1, kw 73 | do idim = 1, ndim 74 | val(idim, kk, jj, ii) = val(idim, kk, jj, ii) + & 75 | basisu(i) * basisv(j) * basisw(k) * & 76 | coef(idim, istartw + k, istartv + j, istartu + i) 77 | end do 78 | end do 79 | end do 80 | end do 81 | end do 82 | end do 83 | end do 84 | end subroutine eval_volume 85 | 86 | subroutine eval_volume_deriv(u, v, w, tu, tv, tw, ku, kv, kw, coef, & 87 | nctlu, nctlv, nctlw, ndim, val) 88 | 89 | !***DESCRIPTION 90 | ! 91 | ! Written by Gaetan Kenway 92 | ! 93 | ! Abstract eval_volume_deriv evaluates the first derivative on a 94 | ! volume 95 | ! 96 | ! Description of Arguments 97 | ! Input 98 | ! u - Real, u coordinate 99 | ! v - Real, v coordinate 100 | ! w - Real, w coordinate 101 | ! tu - Real, Knot vector in u. Length nctlu+ku 102 | ! tv - Real, Knot vector in v. Length nctlv+kv 103 | ! tw - Real, Knot vector in w. Length nctlv+kw 104 | ! ku - Integer, order of B-spline in u 105 | ! kv - Integer, order of B-spline in v 106 | ! kw - Integer, order of B-spline in w 107 | ! coef - Real, Array of B-spline coefficients 108 | ! Size (ndim, nctlw, nctlv, nctlu) 109 | ! nctlu - Integer, Number of control points in u 110 | ! nctlv - Integer, Number of control points in v 111 | ! nctlw - Integer, Number of control points in w 112 | ! ndim - Integer, Spatial Dimension 113 | ! 114 | ! Ouput 115 | ! val - Real, Evaluated derivatvie, size(ndim, 3) 116 | 117 | use precision 118 | implicit none 119 | 120 | ! Input 121 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw, ndim 122 | real(kind=realType), intent(in) :: u, v, w 123 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 124 | real(kind=realType), intent(in) :: coef(ndim, nctlw, nctlv, nctlu) 125 | 126 | ! Output 127 | real(kind=realType), intent(out) :: val(ndim, 3) 128 | 129 | ! Working 130 | integer :: idim 131 | real(kind=realType) :: b3val 132 | 133 | do idim = 1, ndim 134 | val(idim, 1) = b3val(w, v, u, 0, 0, 1, tw, tv, tu, nctlw, nctlv, nctlu, & 135 | kw, kv, ku, coef(idim, :, :, :)) 136 | 137 | val(idim, 2) = b3val(w, v, u, 0, 1, 0, tw, tv, tu, nctlw, nctlv, nctlu, & 138 | kw, kv, ku, coef(idim, :, :, :)) 139 | 140 | val(idim, 3) = b3val(w, v, u, 1, 0, 0, tw, tv, tu, nctlw, nctlv, nctlu, & 141 | kw, kv, ku, coef(idim, :, :, :)) 142 | end do 143 | end subroutine eval_volume_deriv 144 | 145 | subroutine eval_volume_deriv2(u, v, w, tu, tv, tw, ku, kv, kw, coef, & 146 | nctlu, nctlv, nctlw, ndim, val) 147 | 148 | !***DESCRIPTION 149 | ! 150 | ! Written by Gaetan Kenway 151 | ! 152 | ! Abstract eval_volume_deriv2 evaluates the second derivative on a 153 | ! volume 154 | ! 155 | ! Description of Arguments 156 | ! Input 157 | ! u - Real, u coordinate 158 | ! v - Real, v coordinate 159 | ! w - Real, w coordinate 160 | ! tu - Real, Knot vector in u. Length nctlu+ku 161 | ! tv - Real, Knot vector in v. Length nctlv+kv 162 | ! tw - Real, Knot vector in w. Length nctlv+kw 163 | ! ku - Integer, order of B-spline in u 164 | ! kv - Integer, order of B-spline in v 165 | ! kw - Integer, order of B-spline in w 166 | ! coef - Real, Array of B-spline coefficients 167 | ! Size (ndim, nctlw, nctlv, nctlu) 168 | ! nctlu - Integer, Number of control points in u 169 | ! nctlv - Integer, Number of control points in v 170 | ! nctlw - Integer, Number of control points in w 171 | ! ndim - Integer, Spatial Dimension 172 | ! 173 | ! Ouput 174 | ! val - Real, Evaluated derivatvie, size(ndim, 3, 3) 175 | 176 | use precision 177 | implicit none 178 | ! Input 179 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw, ndim 180 | real(kind=realType), intent(in) :: u, v, w 181 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 182 | real(kind=realType), intent(in) :: coef(ndim, nctlw, nctlv, nctlu) 183 | 184 | ! Output 185 | real(kind=realType), intent(out) :: val(ndim, 3, 3) 186 | 187 | ! Working 188 | integer :: idim 189 | 190 | real(kind=realType) :: b3val 191 | 192 | do idim = 1, ndim 193 | 194 | ! Row 1 195 | if (ku >= 3) then 196 | val(idim, 1, 1) = b3val(w, v, u, 0, 0, 2, tw, tv, tu, nctlw, nctlv, & 197 | nctlu, kw, kv, ku, coef(idim, :, :, :)) 198 | else 199 | val(idim, 1, 1) = 0.0 200 | end if 201 | val(idim, 1, 2) = b3val(w, v, u, 0, 1, 1, tw, tv, tu, nctlw, nctlv, nctlu, & 202 | kw, kv, ku, coef(idim, :, :, :)) 203 | val(idim, 1, 3) = b3val(w, v, u, 1, 0, 1, tw, tv, tu, nctlw, nctlv, nctlu, & 204 | kw, kv, ku, coef(idim, :, :, :)) 205 | 206 | ! Row 2 207 | val(idim, 2, 1) = val(idim, 1, 2) 208 | if (kv >= 3) then 209 | val(idim, 2, 2) = b3val(w, v, u, 0, 2, 0, tw, tv, tu, nctlw, nctlv, & 210 | nctlu, kw, kv, ku, coef(idim, :, :, :)) 211 | else 212 | val(idim, 2, 2) = 0.0 213 | end if 214 | val(idim, 2, 3) = b3val(w, v, u, 1, 1, 0, tw, tv, tu, nctlw, nctlv, nctlu, & 215 | kw, kv, ku, coef(idim, :, :, :)) 216 | 217 | ! Row 3 218 | val(idim, 3, 1) = val(idim, 1, 3) 219 | val(idim, 3, 2) = val(idim, 2, 3) 220 | if (kw >= 3) then 221 | val(idim, 3, 3) = b3val(w, v, u, 2, 0, 0, tw, tv, tu, nctlw, nctlv, & 222 | nctlu, kw, kv, ku, coef(idim, :, :, :)) 223 | else 224 | val(idim, 3, 3) = 0.0 225 | end if 226 | end do 227 | 228 | end subroutine eval_volume_deriv2 229 | -------------------------------------------------------------------------------- /src/evaluations.f90: -------------------------------------------------------------------------------- 1 | function bvalu(t, coef, nctl, K, ideriv, s) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract bvalu is the generic 1D spline interpolant 8 | ! function. It is similar to the function of the same 9 | ! name from the tensbs library without the work arrays 10 | ! 11 | ! Description of Arguments 12 | ! Input 13 | ! t - Real, Knot vector. Length nctl+k 14 | ! coef - Real, Array of b-sline coefficients Size (nctl) 15 | ! nctl - Integer, Number of control points 16 | ! k - Integer, order of B-spline 17 | ! ideriv - Integer, degree of derivatve to evaluate 18 | ! s - Real, Position to evaluate 19 | ! 20 | ! Ouput bvalu - Real, Evaluated point or derivative 21 | 22 | use precision 23 | implicit none 24 | 25 | ! Input 26 | integer, intent(in) :: k, nctl, ideriv 27 | real(kind=realType), intent(in) :: s 28 | real(kind=realType), intent(in) :: t(nctl + k) 29 | real(kind=realType), intent(in) :: coef(nctl) 30 | 31 | ! Output 32 | real(kind=realType) :: bvalu 33 | 34 | ! Working 35 | integer :: l, istart, ileft 36 | real(kind=realType) :: B(k), Bd(ideriv + 1, k) 37 | 38 | bvalu = 0.0 39 | 40 | ! Find knot span 41 | call findSpan(s, k, t, nctl, ileft) 42 | istart = ileft - k 43 | if (ideriv == 0) then ! Use basis function 44 | call basis(t, nctl, k, s, ileft, B) 45 | do l = 1, k 46 | bvalu = bvalu + B(l) * coef(istart + l) 47 | end do 48 | else 49 | ! Evalute derivative basis functions up to depree specified by 50 | ! ideriv 51 | call derivBasis(t, nctl, k, s, ileft, ideriv, Bd) 52 | do l = 1, k 53 | bvalu = bvalu + Bd(ideriv + 1, l) * coef(istart + l) 54 | end do 55 | end if 56 | end function bvalu 57 | 58 | function b2val(u, v, idu, idv, tu, tv, nctlu, nctlv, ku, kv, coef) 59 | 60 | !***DESCRIPTION 61 | ! 62 | ! Written by Gaetan Kenway 63 | ! 64 | ! Abstract bvalu is the generic 2D spline interpolant 65 | ! function. It is similar to the function of the same 66 | ! name from the tensbs library without the work array 67 | ! 68 | ! Description of Arguments 69 | ! Input 70 | ! u - Real, parametric position 1 71 | ! v - Real, parametric position 2 72 | ! idu - Integer, derivative in u to evaluate 73 | ! idv - Integer, derivative in v to evaluate 74 | ! tu - Real, U Knot vector. Length nctlu+ku 75 | ! tv - Real, V Knot vector. Length nctlv+kv 76 | ! Nctlu - Integer, Number of u control points 77 | ! Nctlv - Integer, Number of v control points 78 | ! ku - Integer, order of spline in u direction 79 | ! kv - Integer, order of spline in v direction 80 | ! coef - Real, Array size Nctlu x Nctlv, B-spline coefficients 81 | ! 82 | ! Ouput 83 | ! b2val - Real, Evaluated point or derivative 84 | 85 | use precision 86 | implicit none 87 | 88 | ! Input 89 | integer, intent(in) :: ku, kv, nctlu, nctlv, idu, idv 90 | real(kind=realType), intent(in) :: u, v, tu(nctlu + ku), tv(nctlv + kv) 91 | real(kind=realType), intent(in) :: coef(nctlu, nctlv) 92 | 93 | ! Output 94 | real(kind=realType) :: b2val 95 | 96 | ! Working 97 | integer :: i, j 98 | integer :: ileftu, ileftv, istartu, istartv 99 | real(kind=realType) :: Bu(ku), Bv(kv) 100 | real(kind=realType) :: Bud(idu + 1, ku), Bvd(idv + 1, kv) 101 | 102 | ! Find knot spans 103 | call findSpan(u, ku, tu, nctlu, ileftu) 104 | istartu = ileftu - ku 105 | 106 | call findSpan(v, kv, tv, nctlv, ileftv) 107 | istartv = ileftv - kv 108 | 109 | b2val = 0.0 110 | 111 | ! Check if we can just use regular basis functions: 112 | if (idu + idv == 0) then 113 | call basis(tu, nctlu, ku, u, ileftu, Bu) 114 | call basis(tv, nctlv, kv, v, ileftv, Bv) 115 | 116 | do i = 1, ku 117 | do j = 1, kv 118 | b2val = b2val + Bu(i) * Bv(j) * coef(istartu + i, istartv + j) 119 | end do 120 | end do 121 | else 122 | ! We need derivative basis functions 123 | call derivBasis(tu, nctlu, ku, u, ileftu, idu, Bud) 124 | call derivBasis(tv, nctlv, kv, v, ileftv, idv, Bvd) 125 | 126 | do i = 1, ku 127 | do j = 1, kv 128 | b2val = b2val + Bud(idu + 1, i) * Bvd(idv + 1, j) * coef(istartu + i, istartv + j) 129 | end do 130 | end do 131 | end if 132 | 133 | end function b2val 134 | 135 | function b3val(u, v, w, idu, idv, idw, tu, tv, tw, nctlu, nctlv, nctlw, & 136 | ku, kv, kw, coef) 137 | 138 | !***DESCRIPTION 139 | ! 140 | ! Written by Gaetan Kenway 141 | ! 142 | ! Abstract bvalu is the generic 2D spline interpolant 143 | ! function. It is similar to the function of the same 144 | ! name from the tensbs library without the work array 145 | ! 146 | ! Description of Arguments 147 | ! Input 148 | ! u - Real, parametric position 1 149 | ! v - Real, parametric position 2 150 | ! w - Real, parametric position 3 151 | ! idu - Integer, derivative in u to evaluate 152 | ! idv - Integer, derivative in v to evaluate 153 | ! idw - Integer, derivative in w to evaluate 154 | ! tu - Real, U Knot vector. Length nctlu+ku 155 | ! tv - Real, V Knot vector. Length nctlv+kv 156 | ! tv - Real, W Knot vector. Length nctlw+kw 157 | ! Nctlu - Integer, Number of u control points 158 | ! Nctlv - Integer, Number of v control points 159 | ! Nctlw - Integer, Number of w control points 160 | ! ku - Integer, order of spline in u direction 161 | ! kv - Integer, order of spline in v direction 162 | ! kw - Integer, order of spline in w direction 163 | ! coef - Real, Array size Nctlu x Nctlv x Nctlw, B-spline coefficients 164 | ! 165 | ! Ouput 166 | ! b3val - Real, Evaluated point or derivative 167 | 168 | use precision 169 | implicit none 170 | 171 | ! Input 172 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw 173 | integer, intent(in) :: idu, idv, idw 174 | real(kind=realType), intent(in) :: u, v, w 175 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 176 | real(kind=realType), intent(in) :: coef(nctlu, nctlv, nctlw) 177 | 178 | ! Output 179 | real(kind=realType) :: b3val 180 | 181 | ! Working 182 | integer :: i, j, k 183 | integer :: ileftu, ileftv, ileftw 184 | integer :: istartu, istartv, istartw 185 | real(kind=realType) :: Bu(ku), Bv(kv), Bw(kw) 186 | real(kind=realType) :: Bud(idu + 1, ku) 187 | real(kind=realType) :: Bvd(idv + 1, kv) 188 | real(kind=realType) :: Bwd(idw + 1, kw) 189 | 190 | ! Find knot spans 191 | call findSpan(u, ku, tu, nctlu, ileftu) 192 | istartu = ileftu - ku 193 | 194 | call findSpan(v, kv, tv, nctlv, ileftv) 195 | istartv = ileftv - kv 196 | 197 | call findSpan(w, kw, tw, nctlw, ileftw) 198 | istartw = ileftw - kw 199 | 200 | b3val = 0.0 201 | 202 | ! Check if we can just use regular basis functions: 203 | if (idu + idv + idw == 0) then 204 | call basis(tu, nctlu, ku, u, ileftu, Bu) 205 | call basis(tv, nctlv, kv, v, ileftv, Bv) 206 | call basis(tw, nctlw, kw, w, ileftw, Bw) 207 | 208 | do i = 1, ku 209 | do j = 1, kv 210 | do k = 1, kw 211 | b3val = b3val + Bu(i) * Bv(j) * Bw(k) * & 212 | coef(istartu + i, istartv + j, istartw + k) 213 | end do 214 | end do 215 | end do 216 | else 217 | ! We need derivative basis functions 218 | call derivBasis(tu, nctlu, ku, u, ileftu, idu, Bud) 219 | call derivBasis(tv, nctlv, kv, v, ileftv, idv, Bvd) 220 | call derivBasis(tw, nctlw, kw, w, ileftw, idw, Bwd) 221 | 222 | do i = 1, ku 223 | do j = 1, kv 224 | do k = 1, kw 225 | b3val = b3val + Bud(idu + 1, i) * Bvd(idv + 1, j) * Bwd(idw + 1, k) * & 226 | coef(istartu + i, istartv + j, istartw + k) 227 | end do 228 | end do 229 | end do 230 | end if 231 | 232 | end function b3val 233 | 234 | ! Also define complex versions --- these are only here for 235 | ! TACS. pySpline doesn't need them 236 | 237 | function cbvalu(t, coef, nctl, K, ideriv, s) 238 | 239 | !***DESCRIPTION 240 | ! 241 | ! Written by Gaetan Kenway 242 | ! 243 | ! Abstract bvalu is the generic 1D spline interpolant 244 | ! function. It is similar to the function of the same 245 | ! name from the tensbs library without the work arrays 246 | ! 247 | ! Description of Arguments 248 | ! Input 249 | ! t - Real, Knot vector. Length nctl+k 250 | ! coef - Complex, Array of b-sline coefficients Size (nctl) 251 | ! nctl - Integer, Number of control points 252 | ! k - Integer, order of B-spline 253 | ! ideriv - Integer, degree of derivatve to evaluate 254 | ! s - Real, Position to evaluate 255 | ! 256 | ! Ouput bvalu - Complex, Evaluated point or derivative 257 | 258 | use precision 259 | implicit none 260 | 261 | ! Input 262 | integer, intent(in) :: k, nctl, ideriv 263 | real(kind=realType), intent(in) :: s 264 | real(kind=realType), intent(in) :: t(nctl + k) 265 | complex(kind=realType), intent(in) :: coef(nctl) 266 | 267 | ! Output 268 | complex(kind=realType) :: cbvalu 269 | 270 | ! Working 271 | integer :: l, istart, ileft 272 | real(kind=realType) :: B(k), Bd(k, k) 273 | 274 | cbvalu = cmplx(0.0, 0.0) 275 | 276 | ! Find knot span 277 | call findSpan(s, k, t, nctl, ileft) 278 | istart = ileft - k 279 | if (ideriv == 0) then ! Use basis function 280 | call basis(t, nctl, k, s, ileft, B) 281 | do l = 1, k 282 | cbvalu = cbvalu + B(l) * coef(istart + l) 283 | end do 284 | else 285 | ! Evalute derivative basis functions up to depree specified by 286 | ! ideriv 287 | call derivBasis(t, nctl, k, s, ileft, ideriv, Bd) 288 | do l = 1, k 289 | cbvalu = cbvalu + Bd(ideriv + 1, l) * coef(istart + l) 290 | end do 291 | end if 292 | end function cbvalu 293 | 294 | function cb2val(u, v, idu, idv, tu, tv, nctlu, nctlv, ku, kv, coef) 295 | 296 | !***DESCRIPTION 297 | ! 298 | ! Written by Gaetan Kenway 299 | ! 300 | ! Abstract bvalu is the generic 2D spline interpolant 301 | ! function. It is similar to the function of the same 302 | ! name from the tensbs library without the work array 303 | ! 304 | ! Description of Arguments 305 | ! Input 306 | ! u - Real, parametric position 1 307 | ! v - Real, parametric position 2 308 | ! idu - Integer, derivative in u to evaluate 309 | ! idv - Integer, derivative in v to evaluate 310 | ! tu - Real, U Knot vector. Length nctlu+ku 311 | ! tv - Real, V Knot vector. Length nctlv+kv 312 | ! Nctlu - Integer, Number of u control points 313 | ! Nctlv - Integer, Number of v control points 314 | ! ku - Integer, order of spline in u direction 315 | ! kv - Integer, order of spline in v direction 316 | ! coef - Complex, Array size Nctlu x Nctlv, B-spline coefficients 317 | ! 318 | ! Ouput 319 | ! b2val - Complex, Evaluated point or derivative 320 | 321 | use precision 322 | implicit none 323 | 324 | ! Input 325 | integer, intent(in) :: ku, kv, nctlu, nctlv, idu, idv 326 | real(kind=realType), intent(in) :: u, v, tu(nctlu + ku), tv(nctlv + kv) 327 | complex(kind=realType), intent(in) :: coef(nctlu, nctlv) 328 | 329 | ! Output 330 | complex(kind=realType) :: cb2val 331 | 332 | ! Working 333 | integer :: i, j 334 | integer :: ileftu, ileftv, istartu, istartv 335 | real(kind=realType) :: Bu(ku), Bv(kv) 336 | real(kind=realType) :: Bud(ku, ku), Bvd(kv, kv) 337 | 338 | ! Find knot spans 339 | call findSpan(u, ku, tu, nctlu, ileftu) 340 | istartu = ileftu - ku 341 | 342 | call findSpan(v, kv, tv, nctlv, ileftv) 343 | istartv = ileftv - kv 344 | 345 | cb2val = cmplx(0.0, 0.0) 346 | 347 | ! Check if we can just use regular basis functions: 348 | if (idu + idv == 0) then 349 | call basis(tu, nctlu, ku, u, ileftu, Bu) 350 | call basis(tv, nctlv, kv, v, ileftv, Bv) 351 | 352 | do i = 1, ku 353 | do j = 1, kv 354 | cb2val = cb2val + Bu(i) * Bv(j) * coef(istartu + i, istartv + j) 355 | end do 356 | end do 357 | else 358 | ! We need derivative basis functions 359 | call derivBasis(tu, nctlu, ku, u, ileftu, idu, Bu) 360 | call derivBasis(tv, nctlv, kv, v, ileftv, idv, BV) 361 | 362 | do i = 1, ku 363 | do j = 1, kv 364 | cb2val = cb2val + Bud(idu + 1, i) * Bvd(idv + 1, j) * coef(istartu + i, istartv + j) 365 | end do 366 | end do 367 | end if 368 | 369 | end function cb2val 370 | 371 | function cb3val(u, v, w, idu, idv, idw, tu, tv, tw, nctlu, nctlv, nctlw, & 372 | ku, kv, kw, coef) 373 | 374 | !***DESCRIPTION 375 | ! 376 | ! Written by Gaetan Kenway 377 | ! 378 | ! Abstract bvalu is the generic 2D spline interpolant 379 | ! function. It is similar to the function of the same 380 | ! name from the tensbs library without the work array 381 | ! 382 | ! Description of Arguments 383 | ! Input 384 | ! u - Real, parametric position 1 385 | ! v - Real, parametric position 2 386 | ! w - Real, parametric position 3 387 | ! idu - Integer, derivative in u to evaluate 388 | ! idv - Integer, derivative in v to evaluate 389 | ! idw - Integer, derivative in w to evaluate 390 | ! tu - Real, U Knot vector. Length nctlu+ku 391 | ! tv - Real, V Knot vector. Length nctlv+kv 392 | ! tv - Real, W Knot vector. Length nctlw+kw 393 | ! Nctlu - Integer, Number of u control points 394 | ! Nctlv - Integer, Number of v control points 395 | ! Nctlw - Integer, Number of w control points 396 | ! ku - Integer, order of spline in u direction 397 | ! kv - Integer, order of spline in v direction 398 | ! kw - Integer, order of spline in w direction 399 | ! coef - Complex, Array size Nctlu x Nctlv x Nctlw, B-spline coefficients 400 | ! 401 | ! Ouput 402 | ! b3val - Complex, Evaluated point or derivative 403 | 404 | use precision 405 | implicit none 406 | 407 | ! Input 408 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw 409 | integer, intent(in) :: idu, idv, idw 410 | real(kind=realType), intent(in) :: u, v, w 411 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 412 | complex(kind=realType), intent(in) :: coef(nctlu, nctlv, nctlw) 413 | 414 | ! Output 415 | complex(kind=realType) :: cb3val 416 | 417 | ! Working 418 | integer :: i, j, k 419 | integer :: ileftu, ileftv, ileftw 420 | integer :: istartu, istartv, istartw 421 | real(kind=realType) :: Bu(ku), Bv(kv), Bw(kw) 422 | real(kind=realType) :: Bud(ku, ku), Bvd(kv, kv), Bwd(kw, kw) 423 | 424 | ! Find knot spans 425 | call findSpan(u, ku, tu, nctlu, ileftu) 426 | istartu = ileftu - ku 427 | 428 | call findSpan(v, kv, tv, nctlv, ileftv) 429 | istartv = ileftv - kv 430 | 431 | call findSpan(w, kw, tw, nctlw, ileftw) 432 | istartw = ileftw - kw 433 | 434 | cb3val = cmplx(0.0, 0.0) 435 | 436 | ! Check if we can just use regular basis functions: 437 | if (idu + idv + idw == 0) then 438 | call basis(tu, nctlu, ku, u, ileftu, Bu) 439 | call basis(tv, nctlv, kv, v, ileftv, Bv) 440 | call basis(tw, nctlw, kw, w, ileftw, Bw) 441 | 442 | do i = 1, ku 443 | do j = 1, kv 444 | do k = 1, kw 445 | cb3val = cb3val + Bu(i) * Bv(j) * Bw(k) * & 446 | coef(istartu + i, istartv + j, istartw + k) 447 | end do 448 | end do 449 | end do 450 | else 451 | ! We need derivative basis functions 452 | call derivBasis(tu, nctlu, ku, u, ileftu, idu, Bud) 453 | call derivBasis(tv, nctlv, kv, v, ileftv, idv, Bvd) 454 | call derivBasis(tw, nctlw, kw, w, ileftw, idw, Bwd) 455 | 456 | do i = 1, ku 457 | do j = 1, kv 458 | do k = 1, kw 459 | cb3val = cb3val + Bud(idu + 1, i) * Bvd(idv + 1, j) * Bwd(idw + 1, k) * & 460 | coef(istartu + i, istartv + j, istartw + k) 461 | end do 462 | end do 463 | end do 464 | end if 465 | 466 | end function cb3val 467 | -------------------------------------------------------------------------------- /src/f2py/Makefile: -------------------------------------------------------------------------------- 1 | MAIN_DIR = ../.. 2 | COMMON_FILE = $(MAIN_DIR)/Common.mk 3 | RULES_FILE = $(MAIN_DIR)/Rules.mk 4 | include ${COMMON_FILE} 5 | include ${RULES_FILE} 6 | 7 | LINKER_ALL_FLAGS = $(FF90_FLAGS) -L$(LIBDIR) -lspline $(LINKER_FLAGS) 8 | 9 | PYTHON_OBJECTS = fortranobject.o \ 10 | libsplinemodule.o\ 11 | libspline-f2pywrappers2.o\ 12 | 13 | default: all 14 | 15 | all: 16 | 17 | # Generate Python inlude directory 18 | $(eval PYTHON_INCLUDES = $(shell $(PYTHON-CONFIG) --includes)) 19 | @echo "#------------------------------------------------------#" 20 | @echo Python Inclue Flags $(PYTHON_INCLUDES) 21 | @echo "#------------------------------------------------------#" 22 | 23 | # Generate Numpy inlude directory 24 | $(eval NUMPY_INCLUDES = $(shell $(PYTHON) -c 'import numpy; print(numpy.get_include())')) 25 | @echo "#------------------------------------------------------#" 26 | @echo Numpy Include Directory: $(NUMPY_INCLUDES) 27 | @echo "#------------------------------------------------------#" 28 | 29 | # Generate f2py root directory 30 | $(eval F2PY_ROOT = $(shell $(PYTHON) get_f2py.py)) 31 | @echo "#------------------------------------------------------#" 32 | @echo f2py root directory: $(F2PY_ROOT) 33 | @echo "#------------------------------------------------------#" 34 | 35 | # need to have f2py_f2cmap in this folder.... 36 | cp f2py_f2cmap.ref .f2py_f2cmap 37 | 38 | $(F2PY) pyspline.pyf 39 | @echo " " 40 | $(CC) $(CC_FLAGS) $(PYTHON_INCLUDES) -I$(NUMPY_INCLUDES) \ 41 | -I$(F2PY_ROOT)/src -c libsplinemodule.c 42 | 43 | $(CC) $(CC_FLAGS) $(PYTHON_INCLUDES) -I$(NUMPY_INCLUDES) -c \ 44 | $(F2PY_ROOT)/src/fortranobject.c -o fortranobject.o 45 | 46 | # Compiled f2py-generated wrapper file 47 | $(FF90) $(FF90_ALL_FLAGS) -I./ -c libspline-f2pywrappers2.f90 48 | 49 | $(FF90) $(SO_LINKER_FLAGS) $(PYTHON_OBJECTS) $(LINKER_ALL_FLAGS) -o libspline.so 50 | $(PYTHON) importTest.py libspline.so 51 | mv libspline.so ../../pyspline 52 | 53 | # Clean up temporary files 54 | -rm *.o 55 | -rm *.c 56 | -rm .f2py_f2cmap 57 | clean: 58 | @echo " Making clean in f2py... " 59 | rm -f $(MAKE_CLEAN_ARGUMENTS) 60 | -------------------------------------------------------------------------------- /src/f2py/f2py_f2cmap.ref: -------------------------------------------------------------------------------- 1 | {'real':{'realtype':'double'}} -------------------------------------------------------------------------------- /src/f2py/get_f2py.py: -------------------------------------------------------------------------------- 1 | # ------------- VERY IMPORTANT ------------ 2 | 3 | # This script is necessary since f2py INSISTS on priting crap out when 4 | # .f2py_f2cmap exists in the directory. Normally it get deleted, but 5 | # if its still around a more naive approach will fail miseribly. Here 6 | # we temporily reassign stdout such that when we import it, the output 7 | # goes to stdout. Then we reassign stdout and simply puck off the 8 | # include directory. 9 | # Standard Python modules 10 | import os 11 | import sys 12 | 13 | # External modules 14 | import numpy.f2py 15 | 16 | tmp = sys.stdout 17 | sys.stdout = sys.stderr 18 | 19 | sys.stdout = tmp 20 | print(os.path.dirname(os.path.abspath(numpy.f2py.__file__))) 21 | -------------------------------------------------------------------------------- /src/f2py/importTest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # Standard Python modules 3 | import argparse 4 | import os 5 | import sys 6 | 7 | parser = argparse.ArgumentParser() 8 | parser.add_argument( 9 | "name", 10 | type=str, 11 | help="Library name (example: libpackage.so). Note: This script must be run in the same dir as the library.", 12 | ) 13 | args = parser.parse_args() 14 | 15 | # Make sure the executing directory is always in the PATH before importing 16 | sys.path.insert(0, os.getcwd()) 17 | 18 | # Only get the filename without the extension 19 | name = os.path.splitext(args.name)[0] 20 | print(f"Testing if module {name} can be imported...") 21 | 22 | try: 23 | import_cmd = f"import {name}" 24 | exec(import_cmd) 25 | except ImportError as e: 26 | print(f"Error: {e}") 27 | print(f"Error: library {args.name} was not imported correctly") 28 | sys.exit(1) 29 | 30 | print(f"Module {name} was successfully imported") 31 | -------------------------------------------------------------------------------- /src/findSpan.f90: -------------------------------------------------------------------------------- 1 | subroutine findSpan(u, k, t, nctl, ind) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway. Adapted from "The NURBS BooK" Algorithm A2.1 6 | ! 7 | ! Abstract: Determine the knot span index 8 | 9 | ! Description of Arguments 10 | ! Input: 11 | ! u - Real, parametric location we are looking for 12 | ! k - Integer, order of B-spline 13 | ! t - Real, size(nctl + k), knot vector 14 | ! 15 | ! Ouput: 16 | ! ind - Integer, knot span index 17 | 18 | use precision 19 | implicit none 20 | 21 | ! Input 22 | integer, intent(in) :: k, nctl 23 | real(kind=realType), intent(in) :: u, t(nctl + k) 24 | ! Output 25 | integer, intent(out) :: ind 26 | 27 | ! Working 28 | integer :: low, mid, high 29 | 30 | if (u >= t(nctl + 1)) then 31 | ind = nctl 32 | else if (u < t(k)) then 33 | ind = k 34 | else 35 | low = k 36 | high = nctl + 1 37 | 38 | ! Do a binary search 39 | mid = (low + high) / 2 40 | do while ((u < t(mid) .or. u >= t(mid + 1))) 41 | if (u < t(mid)) then 42 | high = mid 43 | else 44 | low = mid 45 | end if 46 | 47 | mid = (low + high) / 2 48 | end do 49 | 50 | ind = mid 51 | end if 52 | 53 | end subroutine findSpan 54 | -------------------------------------------------------------------------------- /src/getBasisPt.f90: -------------------------------------------------------------------------------- 1 | subroutine getBasisPtSurface(u, v, tu, tv, ku, kv, vals, col_ind, istart, l_index, nctlu, nctlv, nnz) 2 | use precision 3 | implicit none 4 | 5 | ! Input/Output 6 | integer, intent(in) :: ku, kv, nctlu, nctlv, nnz, istart 7 | real(kind=realType), intent(in) :: u, v 8 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv) 9 | integer, intent(in) :: l_index(Nctlv, Nctlu) 10 | real(kind=realType), intent(inout) :: vals(nnz) 11 | integer, intent(inout) :: col_ind(nnz) 12 | 13 | ! Working 14 | real(kind=realType) :: basisu(ku), basisv(kv) 15 | integer :: ileftu, ileftv 16 | integer :: ii, jj, counter, start 17 | 18 | ! Get u interval 19 | call findSpan(u, ku, tu, nctlu, ileftu) 20 | call basis(tu, nctlu, ku, u, ileftu, basisu) 21 | 22 | ! Get v interval 23 | call findSpan(v, kv, tv, nctlv, ileftv) 24 | call basis(tv, nctlv, kv, v, ileftv, basisv) 25 | 26 | counter = 0 27 | do ii = 1, ku 28 | do jj = 1, kv 29 | ! Get the local row/col for this surface 30 | start = istart + counter + 1 31 | col_ind(start) = l_index(ileftv - kv + jj, ileftu - ku + ii) 32 | vals(start) = basisu(ii) * basisv(jj) 33 | counter = counter + 1 34 | end do 35 | end do 36 | end subroutine getBasisPtSurface 37 | 38 | subroutine getBasisPtVolume(u, v, w, tu, tv, tw, ku, kv, kw, vals, col_ind, istart, l_index, nctlu, nctlv, nctlw, nnz) 39 | use precision 40 | implicit none 41 | 42 | ! Input 43 | integer, intent(in) :: ku, kv, kw, nctlu, nctlv, nctlw, nnz, istart 44 | real(kind=realType), intent(in) :: u, v, w 45 | real(kind=realType), intent(in) :: tu(nctlu + ku), tv(nctlv + kv), tw(nctlw + kw) 46 | integer, intent(in) :: l_index(Nctlw, Nctlv, Nctlu) 47 | 48 | ! Output 49 | real(kind=realType), intent(inout) :: vals(nnz) 50 | integer, intent(inout) :: col_ind(nnz) 51 | 52 | ! Working 53 | real(kind=realType) :: basisu(ku), basisv(kv), basisw(kw) 54 | integer :: ileftu, ileftv, ileftw 55 | integer :: ii, jj, kk, counter, start 56 | 57 | ! Get u interval 58 | call findSpan(u, ku, tu, nctlu, ileftu) 59 | call basis(tu, nctlu, ku, u, ileftu, basisu) 60 | 61 | ! Get v interval 62 | call findSpan(v, kv, tv, nctlv, ileftv) 63 | call basis(tv, nctlv, kv, v, ileftv, basisv) 64 | 65 | ! Get w interval 66 | call findSpan(w, kw, tw, nctlw, ileftw) 67 | call basis(tw, nctlw, kw, w, ileftw, basisw) 68 | 69 | counter = 0 70 | do ii = 1, ku 71 | do jj = 1, kv 72 | do kk = 1, kw 73 | ! Get the local row/col for this surface 74 | start = istart + counter + 1 75 | col_ind(start) = l_index(ileftw - kw + kk, ileftv - kv + jj, ileftu - ku + ii) 76 | 77 | vals(start) = basisu(ii) * basisv(jj) * basisw(kk) 78 | counter = counter + 1 79 | end do 80 | end do 81 | end do 82 | end subroutine getBasisPtVolume 83 | 84 | -------------------------------------------------------------------------------- /src/insertKnot.f90: -------------------------------------------------------------------------------- 1 | subroutine insertKnot(u, r, t, k, coef, nctl, ndim, t_new, coef_new, ileft) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract insertKnot inserts a knot u into the curve, r times 8 | ! Adapted from "The NURBS Book" Algorithm 5.1 9 | ! Description of Arguments 10 | ! Input 11 | ! u - Real, location of knot to insert 12 | ! r - Integer, Insert r times 13 | ! t - Real,Knot vector. Length nctl+k 14 | ! k - Integer,order of B-spline 15 | ! coef - Real,Array of B-spline coefficients Size (ndim,nctl) 16 | ! nctl - Integer,Number of control points 17 | ! ndim - Integer, dimension of curve 18 | 19 | ! Ouput 20 | ! t_new - Real, vector of lenght(nctl+k+r) 21 | ! coef_new - Real, Array of new cofficients size(ndim,nctl+r) 22 | ! ileft - Integer of position of knot insertion 23 | 24 | use precision 25 | implicit none 26 | 27 | ! Input 28 | integer, intent(inout) :: r 29 | integer, intent(in) :: k, nctl, ndim 30 | real(kind=realType), intent(in) :: u 31 | real(kind=realType), intent(in) :: t(nctl + k) 32 | real(kind=realType), intent(in) :: coef(ndim, nctl) 33 | 34 | ! Output 35 | real(kind=realType), intent(out) :: t_new(nctl + k + r) 36 | real(kind=realType), intent(out) :: coef_new(ndim, nctl + r) 37 | integer, intent(out) :: ileft 38 | 39 | ! Working 40 | integer :: s, i, j, L 41 | real(kind=realType) :: alpha, temp(ndim, k) 42 | 43 | call findSpan(u, k, t, nctl, ileft) 44 | 45 | ! Compute its multiplicity 46 | s = 0 ! Knot multiplicity 47 | mult: do i = 0, k - 1 48 | if (abs(t(ileft - i) - u) < 1e-12) then 49 | s = s + 1 50 | else 51 | exit mult 52 | end if 53 | end do mult 54 | 55 | ! We need to make sure that the requested multipliity r, plus 56 | ! the actual multiplicity of this know is less than (k-1) 57 | 58 | if (s + r + 1 > k) then 59 | r = k - 1 - s 60 | end if 61 | 62 | ! If we *can't* insert the knot, we MUST copy t and coef to t_new 63 | ! and coef_new and return 64 | if (r == 0) then 65 | coef_new(:, 1:nctl) = coef(:, 1:nctl) 66 | t_new(1:nctl + k) = t(1:nctl + k) 67 | return 68 | end if 69 | 70 | ! --------- Load New Knot Vector ------- 71 | do i = 1, ileft 72 | t_new(i) = t(i) 73 | end do 74 | 75 | do i = 1, r 76 | t_new(ileft + i) = u 77 | end do 78 | 79 | do i = ileft + 1, nctl + k 80 | t_new(i + r) = t(i) 81 | end do 82 | 83 | ! -------- Save unaltered Control Points 84 | do i = 1, ileft - (k - 1) 85 | coef_new(:, i) = coef(:, i) 86 | end do 87 | 88 | do i = ileft - s, nctl 89 | coef_new(:, i + r) = coef(:, i) 90 | end do 91 | 92 | do i = 0, k - 1 - s 93 | temp(:, i + 1) = coef(:, ileft - (k - 1) + i) 94 | end do 95 | 96 | do j = 1, r 97 | L = ileft - (k - 1) + j 98 | do i = 0, k - 1 - j - s 99 | alpha = (u - t(L + i)) / (t(i + ileft + 1) - t(L + i)) 100 | temp(:, i + 1) = alpha * temp(:, i + 2) + (1.0 - alpha) * temp(:, i + 1) 101 | end do 102 | coef_new(:, L) = temp(:, 1) 103 | coef_new(:, ileft + r - j - s) = temp(:, k - j - s) 104 | end do 105 | 106 | do i = L + 1, ileft - s - 1 107 | coef_new(:, i) = temp(:, i - L + 1) 108 | end do 109 | 110 | call findSpan(u, k, t_new, nctl + r, ileft) 111 | end subroutine insertKnot 112 | 113 | -------------------------------------------------------------------------------- /src/knots.f90: -------------------------------------------------------------------------------- 1 | subroutine knots_lms(X, N, Nctl, k, t) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract knots_lms generates knots suitable for b-splines 8 | ! 9 | ! Description of Arguments 10 | ! Input 11 | ! X - Real, size(N) The ordinates to use to make knot vector 12 | ! N - Integer, the number of ordinates 13 | ! Nctl - Integer, the desired number of control points 14 | ! k - order of spline 15 | ! 16 | ! Ouput 17 | ! t - Real, size(Nctl+k) the resulting knots 18 | 19 | use precision 20 | implicit none 21 | 22 | ! Input 23 | integer, intent(in) :: N 24 | integer, intent(in) :: Nctl 25 | integer, intent(in) :: K 26 | real(kind=realType), intent(in) :: X(N) 27 | 28 | ! Output 29 | real(kind=realType), intent(out) :: T(Nctl + K) 30 | 31 | ! Working 32 | real(kind=realType) d, alpha 33 | integer I, J 34 | 35 | ! ---------------------------- 36 | ! PUT K KNOTS AT EACH ENDPOINT -- Knot a knot conditions 37 | ! ---------------------------- 38 | ! 39 | DO J = 1, K 40 | t(J) = X(1) ! Left 41 | t(Nctl + J) = X(N) ! right 42 | end do 43 | 44 | if (mod(N, 2) == 1) then ! Odd 45 | d = real(N / (Nctl - k + 1.0)) 46 | do j = 1, Nctl - k 47 | i = floor(j * d) 48 | alpha = j * d - i 49 | t(k + j) = (1 - alpha) * X(i) + alpha * X(i + 2) 50 | end do 51 | else ! even 52 | d = real(N / (Nctl - k + 1.0)) 53 | do j = 1, Nctl - k 54 | i = floor(j * d) 55 | alpha = j * d - i + 0.5 56 | t(k + j) = (1 - alpha) * X(i) + alpha * X(i + 1) 57 | end do 58 | end if 59 | 60 | end subroutine knots_lms 61 | 62 | subroutine knots_interp(X, deriv_ptr, n, nd, k, t) 63 | !***DESCRIPTION 64 | ! 65 | ! Written by Gaetan Kenway 66 | ! 67 | ! Abstract knots_lms generates knots suitable for b-spline 68 | ! interpolation 69 | ! 70 | ! Description of Arguments 71 | ! Input 72 | ! X - Real, size(N) The ordinates to use to make knot vector 73 | ! deriv_ptr - Real, size(nd) Flags to determine if a derivative 74 | ! is specified 75 | ! n - Integer, the number of ordinates 76 | ! nd - Integer, the number of derivatives specified 77 | ! k - order of spline 78 | ! 79 | ! Ouput 80 | ! t - Real, size(nNctl+k) the resulting knots 81 | 82 | use precision 83 | implicit none 84 | 85 | ! Input 86 | integer, intent(in) :: n, nd, k 87 | integer, intent(in) :: deriv_ptr(nd) 88 | real(kind=realType), intent(in) :: X(n) 89 | 90 | ! Output 91 | real(kind=realType), intent(out) :: t(n + nd + k) 92 | 93 | ! Working 94 | integer :: i, j, Nctl 95 | 96 | ! ---------------------------- 97 | ! PUT K KNOTS AT EACH ENDPOINT -- Knot a knot conditions 98 | ! ---------------------------- 99 | Nctl = n + nd 100 | 101 | DO J = 1, K 102 | t(J) = X(1) ! Left 103 | t(Nctl + J) = X(N) ! right 104 | end do 105 | 106 | if (nd == n) then ! Full Length nd so we can use formulas in NURBS book 107 | if (k == 3) then 108 | do i = 1, n - 2 109 | t(k + 2 * i - 1) = 0.5 * (X(i) + X(i + 1)) 110 | t(k + 2 * i) = X(i + 1) 111 | end do 112 | t(Nctl) = 0.5 * (X(n - 1) + 1) 113 | else if (k == 4) then 114 | t(5) = X(2) / 2 115 | t(Nctl) = 0.5 * (X(n - 1) + 1) 116 | do i = 1, n - 3 117 | t(k + 2 * i) = (1.0 / 3.0) * (2 * X(i + 1) + X(i + 2)) 118 | t(k + 2 * i + 1) = (1.0 / 3.0) * (X(i + 1) + 2 * X(i + 2)) 119 | end do 120 | end if 121 | 122 | else if (nd == 0) then 123 | if (k == 2) then 124 | do j = 1, N - k 125 | t(k + j) = X(j + 1) 126 | end do 127 | else if (k == 3) then 128 | do j = 1, N - k 129 | t(k + j) = 0.5 * (X(j + 1) + X(J + 2)) 130 | end do 131 | else if (k == 4) then 132 | do j = 1, N - k 133 | t(K + j) = X(j + 2) 134 | end do 135 | else 136 | print *, 'Error: Interpolation is only available for k=2, 3 or 4' 137 | stop 138 | end if 139 | else 140 | print *, 'Interp_knots with number of derivative != number of points is not yet supported' 141 | stop 142 | end if 143 | end subroutine knots_interp 144 | -------------------------------------------------------------------------------- /src/parameterizations.f90: -------------------------------------------------------------------------------- 1 | subroutine para3d(X, n, m, l, ndim, S, u, v, w) 2 | !***DESCRIPTION 3 | ! 4 | ! Written by Gaetan Kenway 5 | ! 6 | ! Abstract para3d calculates the parametric locations for a 3d block 7 | ! 8 | ! Description of Arguments 9 | 10 | ! Input 11 | ! X - Real, size(ndim, l, m, n): Coordiantes 12 | 13 | ! Output 14 | ! S - Real, size(ndim, l, m, n): The u, v, w parametric positions 15 | ! u - Real, size(n): The averaged u parameters 16 | ! v - Real, size(m): The averaged v parameters 17 | ! w - Real, size(l): The averaged w parameters 18 | 19 | use precision 20 | implicit none 21 | 22 | ! Input 23 | integer, intent(in) :: n, m, l, ndim 24 | real(kind=realType), intent(in) :: X(ndim, l, m, n) 25 | 26 | ! Output 27 | real(kind=realType), intent(out) :: S(ndim, l, m, n) 28 | real(kind=realType), intent(out) :: u(n), v(m), w(l) 29 | 30 | ! Working 31 | integer :: i, j, k 32 | 33 | ! Initialize output 34 | u(:) = 0.0 35 | v(:) = 0.0 36 | w(:) = 0.0 37 | 38 | ! Zero the three low-end faces (or edges if one plane is specified). 39 | 40 | S(1, :, :, 1) = 0.0 41 | S(2, :, 1, :) = 0.0 42 | S(3, 1, :, :) = 0.0 43 | 44 | ! Set up the low-end edge lines because they are missed by the 45 | ! following loops over most of the low-end faces: 46 | 47 | DO I = 2, n 48 | S(1, 1, 1, I) = S(1, 1, 1, I - 1) + DELI(1, 1, I) 49 | END DO 50 | 51 | DO J = 2, m 52 | S(2, 1, J, 1) = S(2, 1, J - 1, 1) + DELJ(1, J, 1) 53 | END DO 54 | 55 | DO K = 2, l 56 | S(3, K, 1, 1) = S(3, k - 1, 1, 1) + DELK(K, 1, 1) 57 | END DO 58 | 59 | ! Set up the rest of the low-end face lines because they are 60 | ! missed by the the main loop over most of the volume. 61 | 62 | DO K = 2, l 63 | DO J = 2, m 64 | S(2, K, J, 1) = S(2, K, J - 1, 1) + DELJ(K, J, 1) 65 | S(3, K, J, 1) = S(3, K - 1, J, 1) + DELK(K, J, 1) 66 | END DO 67 | end DO 68 | 69 | DO I = 2, n 70 | DO K = 2, l 71 | S(1, K, 1, I) = S(1, K, 1, I - 1) + DELI(K, 1, I) 72 | S(3, K, 1, I) = S(3, K - 1, 1, I) + DELK(K, 1, I) 73 | END DO 74 | 75 | END DO 76 | 77 | DO I = 2, n 78 | DO J = 2, m 79 | S(1, 1, J, I) = S(1, 1, J, I - 1) + DELI(1, J, I) 80 | S(2, 1, J, I) = S(2, 1, J - 1, I) + DELJ(1, J, I) 81 | END DO 82 | END DO 83 | 84 | ! Traverse the block just once for all lines except those within 85 | ! the low-end faces. 86 | 87 | DO I = 2, n 88 | DO J = 2, m 89 | DO K = 2, l 90 | S(1, K, J, I) = S(1, K, J, I - 1) + DELI(K, J, I) 91 | S(2, K, J, I) = S(2, K, J - 1, I) + DELJ(K, J, I) 92 | S(3, K, J, I) = S(3, K - 1, J, I) + DELK(K, J, I) 93 | END DO 94 | END DO 95 | END DO 96 | 97 | ! Normalizing requires another pass through the volume. 98 | ! Handle lines of zero length first by inserting uniform 99 | ! distributions. Then the standard normalization can be 100 | ! applied safely everywhere. 101 | 102 | DO J = 1, m 103 | ! Zero-length lines in the I direction? 104 | 105 | DO K = 1, l 106 | IF (S(1, K, J, n) == 0.0) THEN 107 | DO I = 2, n 108 | S(1, K, J, I) = I - 1 109 | END DO 110 | END IF 111 | END DO 112 | end DO 113 | 114 | ! Zero-length lines in the J direction? 115 | DO I = 1, n 116 | DO K = 1, l 117 | IF (S(2, K, m, I) == 0.0) THEN 118 | DO J = 2, m 119 | S(2, K, J, I) = J - 1 120 | END DO 121 | END IF 122 | END DO 123 | END DO 124 | 125 | ! Zero-length lines in the K direction? 126 | 127 | DO I = 1, n 128 | DO J = 1, m 129 | IF (S(3, l, J, I) == 0.0) THEN 130 | DO K = 2, l 131 | S(3, K, J, I) = K - 1 132 | END DO 133 | END IF 134 | END DO 135 | END DO 136 | 137 | ! Normalize: 138 | 139 | DO I = 1, n 140 | DO J = 1, m 141 | DO K = 1, l 142 | S(1, K, J, I) = S(1, K, J, I) / S(1, K, J, N) 143 | S(2, K, J, I) = S(2, K, J, I) / S(2, K, M, I) 144 | S(3, K, J, I) = S(3, K, J, I) / S(3, L, J, I) 145 | END DO 146 | END DO 147 | END DO 148 | 149 | ! Finally, precise 1s for the three high-end faces: 150 | 151 | DO J = 1, m 152 | DO K = 1, l 153 | S(1, K, J, n) = 1.0 154 | END DO 155 | end DO 156 | 157 | DO I = 1, n 158 | DO K = 1, l 159 | S(2, K, M, I) = 1.0 160 | END DO 161 | END DO 162 | 163 | DO I = 1, n 164 | DO J = 1, m 165 | S(3, L, J, I) = 1.0 166 | END DO 167 | END DO 168 | 169 | ! Now get an average u, v, w 170 | 171 | ! Average u 172 | 173 | do j = 1, m 174 | do k = 1, l 175 | u = u + S(1, k, j, :) 176 | end do 177 | end do 178 | u = u / (l * m) 179 | 180 | ! Average v 181 | do i = 1, n 182 | do k = 1, l 183 | v = v + S(2, k, :, i) 184 | end do 185 | end do 186 | v = v / (n * l) 187 | 188 | ! Average w 189 | do i = 1, n 190 | do j = 1, m 191 | w = w + S(3, :, j, i) 192 | end do 193 | end do 194 | w = w / (n * m) 195 | 196 | contains 197 | pure real(kind=realType) function DELI(kk, jj, ii) 198 | integer, intent(in) :: kk, jj, ii 199 | 200 | DELI = SQRT((X(1, kk, jj, ii) - X(1, kk, jj, ii - 1))**2 + & 201 | (X(2, kk, jj, ii) - X(2, kk, jj, ii - 1))**2 + & 202 | (X(3, kk, jj, ii) - X(3, kk, jj, ii - 1))**2) 203 | end function DELI 204 | 205 | pure real(kind=realType) function DELJ(kk, jj, ii) 206 | integer, intent(in) :: kk, jj, ii 207 | 208 | DELJ = SQRT((X(1, kk, jj, ii) - X(1, kk, jj - 1, ii))**2 + & 209 | (X(2, kk, jj, ii) - X(2, kk, jj - 1, ii))**2 + & 210 | (X(3, kk, jj, ii) - X(3, kk, jj - 1, ii))**2) 211 | end function DELJ 212 | 213 | pure real(kind=realType) function DELK(kk, jj, ii) 214 | integer, intent(in) :: kk, jj, ii 215 | 216 | DELK = SQRT((X(1, kk, jj, ii) - X(1, kk - 1, jj, ii))**2 + & 217 | (X(2, kk, jj, ii) - X(2, kk - 1, jj, ii))**2 + & 218 | (X(3, kk, jj, ii) - X(3, kk - 1, jj, ii))**2) 219 | end function DELK 220 | 221 | end subroutine para3d 222 | -------------------------------------------------------------------------------- /src/precision.f90: -------------------------------------------------------------------------------- 1 | module precision 2 | 3 | integer, parameter :: realType = selected_real_kind(12) 4 | 5 | end module precision 6 | -------------------------------------------------------------------------------- /src/tfi2d.f90: -------------------------------------------------------------------------------- 1 | subroutine tfi2d(e0, e1, e2, e3, Nu, Nv, X) 2 | 3 | !***DESCRIPTION 4 | ! 5 | ! Written by Gaetan Kenway 6 | ! 7 | ! Abstract: Perform a simple 2D transfinite interpolation in 3 8 | ! spatial dimensions. This function is not used 9 | ! directly in pySpline, but from pyGeo. 10 | ! 11 | ! Description of Arguments 12 | ! Input 13 | ! e0 - Real, Vector or coordinates along 0th edge. Size (3, Nu) 14 | ! e1 - Real, Vector or coordinates along 1st edge. Size (3, Nu) 15 | ! e2 - Real, Vector or coordinates along 2nd edge. Size (3, Nv) 16 | ! e3 - Real, Vector or coordinates along 3rd edge. Size (3, Nv) 17 | ! 18 | ! Ouput 19 | ! X - Real, Evaluated points, size 3 x Nu x Nv 20 | ! 21 | 22 | use precision 23 | implicit none 24 | 25 | integer, intent(in) :: Nu, Nv 26 | real(kind=realType), intent(in) :: e0(3, Nu) 27 | real(kind=realType), intent(in) :: e1(3, Nu) 28 | 29 | real(kind=realType), intent(in) :: e2(3, Nv) 30 | real(kind=realType), intent(in) :: e3(3, Nv) 31 | 32 | real(kind=realType), intent(out) :: X(3, Nv, Nu) 33 | 34 | real(kind=realType) :: U(Nu), V(Nv) 35 | integer :: i, j 36 | 37 | do i = 1, Nu 38 | U(i) = real(i - 1) / (Nu - 1) 39 | end do 40 | 41 | do j = 1, Nv 42 | V(j) = real(j - 1) / (Nv - 1) 43 | end do 44 | 45 | do i = 1, Nu 46 | do j = 1, Nv 47 | X(:, j, i) = (1 - V(j)) * e0(:, i) + V(j) * e1(:, i) + & 48 | (1 - U(i)) * e2(:, j) + U(i) * e3(:, j) - ( & 49 | (U(i)) * (V(j)) * e1(:, Nu) + & 50 | (U(i)) * (1 - V(j)) * e0(:, Nu) + & 51 | (1 - U(i)) * (V(j)) * e1(:, 1) + & 52 | (1 - U(i)) * (1 - V(j)) * e0(:, 1) & 53 | ) 54 | end do 55 | end do 56 | 57 | end subroutine tfi2d 58 | -------------------------------------------------------------------------------- /tests/reg_tests/test_curves.py: -------------------------------------------------------------------------------- 1 | # Standard Python modules 2 | import os 3 | import unittest 4 | 5 | # External modules 6 | from baseclasses import BaseRegTest 7 | import numpy as np 8 | from numpy.testing import assert_allclose 9 | 10 | # First party modules 11 | from pyspline import Curve 12 | 13 | baseDir = os.path.dirname(os.path.abspath(__file__)) 14 | 15 | 16 | def eval_test(crv, handler, test_name): 17 | """Eval fixed points from the curve""" 18 | # ----------- Evaluation and derivative functions --------------- 19 | pts = [0.0, 0.5, 0.75, 1.0] 20 | for pt in pts: 21 | # print('Testing pt %f'%(pt)) 22 | # print('Value:') 23 | handler.root_add_val("{} curve evaluated at {}".format(test_name, pt), crv(pt)) 24 | # print('Deriv:') 25 | handler.root_add_val("{} curve derivative evaluated at {}".format(test_name, pt), crv.getDerivative(pt)) 26 | # print('Second Derivative') 27 | handler.root_add_val( 28 | "{} curve second derivative evaluated at {}".format(test_name, pt), crv.getSecondDerivative(pt), tol=1e-10 29 | ) 30 | 31 | 32 | def run_curve_test(crv, handler, test_name): 33 | """This function is used to test the functions that are apart of 34 | the curve class. They operate on the 'crv' that is passed.""" 35 | 36 | # Test the evaluations 37 | eval_test(crv, handler, "{} initial".format(test_name)) 38 | 39 | # Inset a knot at 0.25 with multiplicity of k-1 and retest 40 | crv.insertKnot(0.25, crv.k - 1) 41 | # print('------- Cruve with inserted knots ----------') 42 | eval_test(crv, handler, "{} inserted knots".format(test_name)) 43 | 44 | handler.root_add_val("{} curve length".format(test_name), crv.getLength()) 45 | 46 | a = 0.1 47 | b = 0.9 48 | curve_windowed = crv.windowCurve(a, b) 49 | c = 0.2 50 | assert_allclose( 51 | crv(c), curve_windowed((c - a) / (b - a)), rtol=1e-7, atol=1e-15, err_msg="points do not match after windowing!" 52 | ) 53 | 54 | # Split the curve in two: 55 | curve1, curve2 = crv.splitCurve(0.5) 56 | c1 = curve1(1.0) 57 | c2 = curve2(0.0) 58 | c3 = crv(0.5) 59 | # These three points should be the same (split curve test) 60 | assert_allclose(c1, c2, rtol=1e-7, atol=1e-15, err_msg="points do not match after splitting curve") 61 | assert_allclose(c1, c3, rtol=1e-7, atol=1e-15, err_msg="points do not match after splitting curve") 62 | 63 | # Reverse test: 64 | c1 = crv(0.4) 65 | crv.reverse() 66 | c2 = crv(0.6) 67 | assert_allclose(c1, c2, rtol=1e-7, atol=1e-15, err_msg="points do not match after reversing curve") 68 | 69 | 70 | def run_project_test(crv, handler, test_name): 71 | # Run point projection and curve projection tests' 72 | pts = [[0.4, 1.5, 1.5], [-0.1, 0.5, 1.8], crv(0.75)] 73 | # Default tolerance is 1e-10. so only check to 1e-9 74 | s, D = crv.projectPoint(pts) 75 | for i in range(len(s)): 76 | # print('Project point %f %f %f'%(pts[i][0],pts[i][1],pts[i][2])) 77 | handler.root_add_val("{} projection test for point {} solution".format(test_name, i), s[i], tol=1e-9) 78 | handler.root_add_val("{} projection test for point {} distance".format(test_name, i), D[i], tol=1e-9) 79 | 80 | 81 | def io_test(crv): 82 | """Test the writing functions""" 83 | crv.writeTecplot("tmp_curves.dat") 84 | crv.writeTecplot("tmp_curves.dat", coef=False, orig=False) 85 | os.remove("tmp_curves.dat") 86 | 87 | 88 | class Test(unittest.TestCase): 89 | def setUp(self): 90 | self.ref_file = os.path.join(baseDir, "ref/test_curves.ref") 91 | 92 | def train(self): 93 | with BaseRegTest(self.ref_file, train=True) as handler: 94 | self.regression_test(handler) 95 | handler.writeRef() 96 | 97 | def test(self): 98 | with BaseRegTest(self.ref_file, train=False) as handler: 99 | self.regression_test(handler) 100 | 101 | def regression_test(self, handler): 102 | # print('+--------------------------------------+') 103 | # print(' Create Tests ') 104 | # print('+--------------------------------------+') 105 | # print('----------- 2D k=2 test ----------') 106 | k = 2 107 | t = [0, 0, 0.5, 1, 1] 108 | coef = np.zeros((3, 2)) 109 | coef[0] = [0, 0.6] 110 | coef[1] = [1.1, 1.4] 111 | coef[2] = [2.6, 5.1] 112 | curve = Curve(t=t, k=k, coef=coef) 113 | run_curve_test(curve, handler, "2D k={}".format(k)) 114 | io_test(curve) 115 | 116 | # print('----------- 2D k=3 test ----------') 117 | k = 3 118 | t = [0, 0, 0, 0.5, 1, 1, 1] 119 | coef = np.zeros((4, 2)) 120 | coef[0] = [0, 0.45] 121 | coef[1] = [0.71, 1.5] 122 | coef[2] = [2.5, 5.9] 123 | coef[3] = [4, -2] 124 | curve = Curve(t=t, k=k, coef=coef) 125 | run_curve_test(curve, handler, "2D k={}".format(k)) 126 | io_test(curve) 127 | 128 | # print('----------- 2D k=4 test ----------') 129 | k = 4 130 | t = [0, 0, 0, 0, 0.5, 1, 1, 1, 1] 131 | coef = np.zeros((5, 2)) 132 | coef[0] = [0, -0.60] 133 | coef[1] = [0.9, 1.6] 134 | coef[2] = [1.6, 5.2] 135 | coef[3] = [4.2, -2.24] 136 | coef[4] = [2.9, 6.2] 137 | curve = Curve(t=t, k=k, coef=coef) 138 | run_curve_test(curve, handler, "2D k={}".format(k)) 139 | io_test(curve) 140 | 141 | # Get helix data 142 | n = 100 143 | theta = np.linspace(0.0, np.pi * 2, n) 144 | x = np.cos(theta) 145 | y = np.sin(theta) 146 | z = np.linspace(0, 1, n) 147 | 148 | # print('+--------------------------------------+') 149 | # print(' LMS Tests ') 150 | # print('+--------------------------------------+') 151 | for k in [2, 3, 4]: 152 | test_name = "LMS test k={}".format(k) 153 | # print('--------- Test helix data with k=%d-------'%(k)) 154 | curve = Curve(x=x, y=y, z=z, k=k, nCtl=16, niter=50) 155 | run_curve_test(curve, handler, test_name) 156 | run_project_test(curve, handler, test_name) 157 | 158 | # print('+--------------------------------------+') 159 | # print(' Interp Tests ') 160 | # print('+--------------------------------------+') 161 | for k in [2, 3, 4]: 162 | test_name = "interpolation test k={}".format(k) 163 | # print('--------- Test helix data with k=%d-------'%(k)) 164 | curve = Curve(x=x, y=y, z=z, k=k) 165 | run_curve_test(curve, handler, test_name) 166 | run_project_test(curve, handler, test_name) 167 | -------------------------------------------------------------------------------- /tests/reg_tests/test_surfaces.py: -------------------------------------------------------------------------------- 1 | # Standard Python modules 2 | import os 3 | import unittest 4 | 5 | # External modules 6 | from baseclasses import BaseRegTest 7 | import numpy as np 8 | from numpy.testing import assert_allclose 9 | 10 | # First party modules 11 | from pyspline import Curve, Surface 12 | 13 | baseDir = os.path.dirname(os.path.abspath(__file__)) 14 | 15 | 16 | def eval_test(surface, handler, test_name): 17 | """Eval fixed points from the surface""" 18 | # Evaluations are only good to about 1e-10 since there is fitting 19 | # involved 20 | 21 | # ----------- Evaluation and derivative functions --------------- 22 | pts = [[0, 0], [1, 0], [0, 1], [1, 1], [0.25, 0.25], [0.75, 0.25]] 23 | for pt in pts: 24 | # print('Testing pt (%f %f)'%(pt[0],pt[1])) 25 | handler.root_add_val("{} evaluate point at {}".format(test_name, pt), surface(pt[0], pt[1]), tol=1e-10) 26 | handler.root_add_val( 27 | "{} evaluate point deriv at {}".format(test_name, pt), surface.getDerivative(pt[0], pt[1]), tol=1e-10 28 | ) 29 | handler.root_add_val( 30 | "{} evaluate point second deriv at {}".format(test_name, pt), 31 | surface.getSecondDerivative(pt[0], pt[1]), 32 | tol=1e-8, 33 | ) 34 | 35 | # Orig values at each corner 36 | if surface.origData: 37 | for i in range(4): 38 | handler.root_add_val("{} evaluate corner {}".format(test_name, i), surface.getOrigValueCorner(i)) 39 | 40 | # Orig values on edges 41 | if surface.origData: 42 | for i in range(4): 43 | handler.root_add_val("{} evaluate edge {}".format(test_name, i), surface.getOrigValuesEdge(i)) 44 | 45 | # getValueEdge 46 | for i in [0, 1, 2, 3]: 47 | for j in [0.25, 0.75]: 48 | handler.root_add_val("{} getValueEdge({}, {})".format(test_name, i, j), surface.getValueEdge(i, j)) 49 | 50 | 51 | def run_surface_test(surface, handler, test_name): 52 | """This function is used to test the functions that are apart of 53 | the curve class. They operate on the 'curve' that is passed.""" 54 | 55 | # Test the evaluations 56 | eval_test(surface, handler, test_name) 57 | 58 | # Test the windowing (same surface) 59 | surf2 = surface.windowSurface([0, 0], [1, 1]) 60 | 61 | # Evaluations on surf2 should be same as original 62 | # we use the same test_name to check the same entries 63 | eval_test(surf2, handler, test_name) 64 | 65 | surf2 = surface.windowSurface([0.25, 0.25], [0.75, 0.5]) 66 | # these values should be the same 67 | assert_allclose( 68 | surface(0.25, 0.25), 69 | surf2(0, 0), 70 | rtol=1e-7, 71 | atol=1e-15, 72 | err_msg="surface coordinates do not match after windowing!", 73 | ) 74 | assert_allclose( 75 | surface(0.75, 0.5), 76 | surf2(1, 1), 77 | rtol=1e-7, 78 | atol=1e-15, 79 | err_msg="surface coordinates do not match after windowing!", 80 | ) 81 | 82 | # Test get bounds 83 | handler.root_add_val("{} bounds".format(test_name), surface.getBounds()) 84 | 85 | 86 | def run_project_test(surface, handler, test_name): 87 | # Run a bunch of point projections: Only try to match to 1e-8 88 | eps = 1e-8 89 | 90 | # print('------------- These points should be fully inside of domain') 91 | pts = [[0, 0, 0], [2, 3, -1], [3, 2.5, -0.1]] 92 | for pt in pts: 93 | # print('Projecting point (%f %f %f)'%(pt[0],pt[1],pt[2])) 94 | u, v, D = surface.projectPoint(pt, eps=1e-12) 95 | handler.root_add_val("{} point {} projection u".format(test_name, pt), u, tol=eps) 96 | handler.root_add_val("{} point {} projection v".format(test_name, pt), v, tol=eps) 97 | handler.root_add_val("{} point {} projection D".format(test_name, pt), D, tol=eps * 10) 98 | 99 | # ----------- This should be (0,0) corner 100 | u, v, D = surface.projectPoint([-1, -1, 0], eps=1e-12) 101 | handler.root_add_val("{} projected u for (0,0) corner".format(test_name), u, tol=eps) 102 | handler.root_add_val("{} projected v for (0,0) corner".format(test_name), v, tol=eps) 103 | 104 | # ---------- This should be (0,1) corner 105 | u, v, D = surface.projectPoint([-1, 5, 0], eps=1e-12) 106 | handler.root_add_val("{} projected u for (0,1) corner".format(test_name), u, tol=eps) 107 | handler.root_add_val("{} projected v for (0,1) corner".format(test_name), v, tol=eps) 108 | 109 | # ---------- This should be (1,0) corner 110 | u, v, D = surface.projectPoint([6, -1, 0], eps=1e-12) 111 | handler.root_add_val("{} projected u for (1,0) corner".format(test_name), u, tol=eps) 112 | handler.root_add_val("{} projected v for (1,0) corner".format(test_name), v, tol=eps) 113 | 114 | # ---------- This should be (1,1) corner 115 | u, v, D = surface.projectPoint([6, 6, 0], eps=1e-12) 116 | handler.root_add_val("{} projected u for (1,1) corner".format(test_name), u, tol=eps) 117 | handler.root_add_val("{} projected v for (1,1) corner".format(test_name), v, tol=eps) 118 | 119 | # ---------- This should be edge zero (*,0) 120 | u, v, D = surface.projectPoint([2.54, -1, 0], eps=1e-12) 121 | handler.root_add_val("{} projected u for (*,0) edge".format(test_name), u, tol=eps) 122 | handler.root_add_val("{} projected v for (*,0) edge".format(test_name), v, tol=eps) 123 | 124 | # Curve projection 125 | for kc in [2, 3, 4]: 126 | x = [0, 1, 2, 0] 127 | y = [4, 3, 2, 1] 128 | z = [-3, 1, 3, 5] 129 | 130 | curve = Curve(k=kc, x=x, y=y, z=z) 131 | u, v, s, D = surface.projectCurve(curve) 132 | # ---------- surface-curve projection with kc = kc 133 | handler.root_add_val("{} projected curve u with kc={}".format(test_name, kc), u, tol=eps) 134 | handler.root_add_val("{} projected curve v with kc={}".format(test_name, kc), v, tol=eps) 135 | handler.root_add_val("{} projected curve s with kc={}".format(test_name, kc), s, tol=eps) 136 | handler.root_add_val("{} projected curve D with kc={}".format(test_name, kc), D, tol=eps * 10) 137 | 138 | 139 | def io_test(surface, handler): 140 | """Test the writing functions""" 141 | surface.writeTecplot("tmp.dat", surf=True, coef=True, orig=True, directions=True) 142 | # These three calls, are private functions normally only called 143 | # from pyGeo. We are not checking their output, rather just making 144 | # sure they run. 145 | with open("tmp_surfaces.dat", "w") as f: 146 | surface.writeIGES_directory(f, 0, 0) 147 | surface.writeIGES_parameters(f, 0, 0) 148 | surface.writeTin(f) 149 | os.remove("tmp_surfaces.dat") 150 | 151 | return 152 | 153 | 154 | class Test(unittest.TestCase): 155 | def setUp(self): 156 | self.ref_file = os.path.join(baseDir, "ref/test_surfaces.ref") 157 | 158 | def train(self): 159 | with BaseRegTest(self.ref_file, train=True) as handler: 160 | self.regression_test(handler) 161 | handler.writeRef() 162 | 163 | def test(self): 164 | with BaseRegTest(self.ref_file, train=False) as handler: 165 | self.regression_test(handler) 166 | 167 | def regression_test(self, handler, solve=False): 168 | # Create a generic surface 169 | nu = 10 170 | nv = 10 171 | u = np.linspace(0, 4, nu) 172 | v = np.linspace(0, 4, nv) 173 | [V, U] = np.meshgrid(v, u) 174 | Z = np.cos(U) * np.sin(V) 175 | 176 | # Testing Surface with ku, kv, nCtlu, nCtlv 177 | for ku in [2, 3, 4]: 178 | for kv in [2, 3, 4]: 179 | for nCtlu in [5, 10]: 180 | for nCtlv in [5, 10]: 181 | test_name = "surface with ku={}, kv={}, nCtlu={}, nCtlv={}".format(ku, kv, nCtlu, nCtlv) 182 | surface = Surface(x=U, y=V, z=Z, ku=ku, kv=kv, nCtlu=nCtlu, nCtlv=nCtlv) 183 | surface.recompute() 184 | run_surface_test(surface, handler, test_name) 185 | run_project_test(surface, handler, test_name) 186 | io_test(surface, handler) 187 | --------------------------------------------------------------------------------