2017년 8월 21일 월요일

How to import existing fortran code into python

Since there are many existing fortran codes, it would be better to use them
in python. One possible way to do it is to create a shared object(.so) file by using f2py. 
Simple example of using f2py can be found easily. 
But, in case of complicate fortran program which use 'make',  or in case of the subroutine we want to use is a part of larger library, it is not clear how to 
achieve it. 

The steps are 
(1) Prepare a module code which includes all the subroutines which wants to be 
    ported to python. 
    It is recommended the subroutines includes both input and outputs explicitly 
    by 'intent(in)' and 'intent(out)' properties. 

(2) create a static library for the subroutine (first compile for object files)     
     ar crsv lib[name].a [object files]

(3) use f2py to create signature file (.pyf) . 
    f2py [source file] -m [package name] -h [signature file name]

    Here the [source file] contains the subroutines or its wrapper to be imported to python. signature file (.pyf) contains a module for python which contains subroutines.
Importing sub module does not work well. Thus, always prepare [source file]
as a wrapper with subroutines not modules.

(4) edit the signature fil( .pyf) as necessary. (Only leave the subroutines to be imported) 

(5) created shared object library(.so) file using f2py 
    (If path of library is the same, "-L." would work?) 
    f2py -c [signature file .pyf] [source file] -L[absolute path for library]-l[library name] -llapack

(6) In the python,
    import [package name]

     and now one can use subroutines,
    [packagename].[subroutine]

(7) in case that the library(.so) file is located in different folder,
    add the library path before import

    import sys
    sys.path.insert(0,'[Library Path]')



  • The simple case: If there is only one fortran file, one can do 
  • (1) edit/comment the fortran file "my_lib.f90" with "!f2py " comments or explicit "intent" expressions.
  • (2)  Use following command to create  " my_lib.so " file which can be imported in python by "import my_lib" , 

f2py -c -m my_lib my_lib.f90

# Another way to use f2py is 
   directly add "cf2py intent([in/out]) [variable]" in the fortran source code 
   and compile 
   "python -m numpy.f2py -c -m [module name] [fortran source]" 

# In Windows, there seems to be some issue with the version of mingw-w64. 
  It seems I have to use "x86_64" version of mingw-w64 instead of "i686" version. 
  More details on the installation. 
  (https://python-at-risoe.pages.windenergy.dtu.dk/compiling-on-windows/configuration.html) 

# In Windows, one can use "ar" to create library as like LINUX with mingw-w64.

# Currently(2025.02.25), there seems to be a problem using f2py and "meson" build system in Windows... I am not sure how to fix the error. The same code can be compiled in linux.  --> this can be solved by install "meson" and "ninja" package with "pip" 

#----custumization of docstring of f2py: 
One may want to use custum docstring for f2py generated functions. 
To do this, one needs to overwrite the docstrings. 
(1) Suppose original fortran code have docstring between each "subroutine" and "implicit none" and python package is created by f2py. 
(2) Use the following script after loading the package. 

#-----replace f2py generated docsting with custom docstring from fortran file.  
import re
import special_py as sp # Replace with your actual f2py module name

def extract_fortran_docstrings_by_block(fortran_file_path):
    """
    Parses a Fortran source file to extract documentation blocks 
    between 'subroutine ...' and 'implicit none'.
    """
    docstrings = {}
    with open(fortran_file_path, 'r', encoding='utf-8') as f:
        content = f.read()

    # Regex pattern to capture the text between 'subroutine' (plus the name)
    # and 'implicit none'. Uses re.DOTALL (re.S) for multiline matching.
    # Note: This assumes 'implicit none' appears reliably after the docs you want.
    pattern = re.compile(
        r"subroutine\s+(\w+)\s*\(.*?\).*?(?P<doc_block>.*?)\s*implicit none", 
        re.IGNORECASE | re.DOTALL
    )

    for match in pattern.finditer(content):
        func_name = match.group(1).lower()
        doc_block = match.group('doc_block')

        # Clean up the doc block: remove the '!' prefix and format for Python
        clean_doc_lines = []
        for line in doc_block.strip().splitlines():
            stripped_line = line.strip()
            if stripped_line.startswith('!'):
                # Append everything after the '!' and a single space
                clean_doc_lines.append(stripped_line[1:].strip())
            else:
                # If a line doesn't start with '!' (e.g., blank lines), include it as a blank line
                clean_doc_lines.append("")
        
        docstrings[func_name] = "\n".join(clean_doc_lines).strip()

    return docstrings

def set_custom_docstrings(module, docstring_map):
    """
    Overwrites the docstring for specified functions within a module.
    """
    for func_name, custom_doc in docstring_map.items():
        func_obj = getattr(module, func_name, None)
        if func_obj is not None:
            func_obj.__doc__ = custom_doc
            # Optional: print(f"Docstring for '{func_name}' updated.")

# --- Main Execution ---

# 1. Define the path to your original Fortran source file
FORTRAN_SOURCE = 'special_functions.f90' # Replace with the correct file path

# 2. Extract the docstrings from the Fortran file
try:
    fortran_docs = extract_fortran_docstrings_by_block(FORTRAN_SOURCE)
    
    # 3. Apply the extracted docstrings to the imported Python module functions
    set_custom_docstrings(sp, fortran_docs)
    print(f"Successfully updated docstrings for {len(fortran_docs)} functions.")

    # Verification (Example for airya)
    print("\n--- Updated Docstring for sp.airya ---")
    print(sp.airya.__doc__)

except FileNotFoundError:
    print(f"Error: Could not find the Fortran source file at '{FORTRAN_SOURCE}'")
except Exception as e:
    # Handle potential encoding errors or regex errors
    print(f"An error occurred during processing: {e}")








python library path 설정

Note that the python path is not the same as the system $PATH.

(1) To list the python path,
     import sys
     print(sys.path)

(2) To insert a path,
    sys.path.insert(0, '{PATH TO INSERT}')

    This enables one to import library from other folder.

2017년 5월 16일 화요일

Tikz-Feynman package for Feynman diagram

There have been several packages to draw Feynman diagrams in tex environment.
But I have used two:

Axodraw ( Jaxodraw)
Feynmf (Feynmp)

However, one is rather old and non-standard and the other is not easy to use.

New package "Tikz-Feynman" seems to be good in look and easy in usage.
However, when I try to use the package the diagrams are weird and different shapes
from examples.
The problem was that I compiled them with 'pdflatex'.
It looks like the "Tikz-Feynman" is only compatible with 'lualatex'.
Since it is not written in the manual or webpage, it was difficult to know.

On the other hand, I found each package have advantage and disadvantage.
It is mostly how the vertices are positioned by the command.
For me, Feynmf seems to be better than others. But, because it use metafont,
it is rather slow and I have problem with TexStudio using Feynmf.
(I had to delete metafont whenever I modify them).

2017년 4월 13일 목요일

Shell model code NUSHELL tips

1. In old version of NUSHELL, be careful for the 'psd' model space.
   The single particle levels defined in the 'psd.sp' and interactions like 'psdmk.int'
   may be not consistent.
   The level ordering in original 'psd.sp' file is

   1 1 1 3  (p3/2)
   2 1 1 1  (p1/2)

   But, it have to be changed as follows to be consistent with the definitions in 'psdmk.int' interaction file.

   1 1 1 1  (p1/2)
   2 1 1 3  (p3/2)


---UNDER CONSTRUCTION

2017년 3월 29일 수요일

Python referencing( copying variables, objects)

In many language (at least, in Fortran), '=' makes a copy of a variable, so

a=1; b=a;  b=2

makes a=1 and b=2. Thus any change of the copy does not change the original.
This is the same for python, if the variable is a simple object.

However, in python, 'list1= list2' does not make two lists. Instead it refers the same reference object. Since, if a new value is assigned to the list, it may be okay.

a=[1,2,3]; b=a; b=[4,5,6]

makes a as [1,2,3] and b as [4,5,6] since the last  assignment 'b=[4,5,6]'
can be considered as a new assignment.

However, if we modify its elements,

a=[1,2,3]; b=a ; b[1]=7

makes both a and b as [1,7,3] (instead of a as [1,2,3], b as [1,7,3] )
since a and b were both refer the same object.

To obtain the originally desired effect, one can use

(1) b=a[:]  or b[:]=a[:]
(2) b=list(a)
(3) b=copy.copy(a)






2016년 9월 20일 화요일

범죄수학( 리스 하스아우트)

범죄 수학


리스 하스아우트 지음 | 오혜정 옮김 | 남호영 감수 | GBRAIN | 2010년 07월 23일 출간

추리 소설과 수학을 이상적으로 결합한 책이다. 마치 encyclopedia Brown 처럼, 검사인 아버지의 사건을 아들인 라비가 수학적 지식으로 도움을 주는 형식이다. 사건에 대한 짧은 글과 중요한 내용을 수학문제로 다시 짧게 간추려준 다음, 수학 문제의 답과 사건의 해결방법을 알려준다. 그리고, 나온 수학적 내용을 좀 더 깊이 있게 설명하기도 한다. 
전체적인 문제의 수준은 고등학생이상 (경우에 따라서는  대학생 이상) 이지만, 간단한 대수나 논리 문제는 중학생도 가능할 것으로 보인다. 이전의 짧은 콩트 형식의 추리 퀴즈나 퍼즐들에 비해 난이도가 높은 편이지만, 상당히 재미있게 읽을 수 있었다. 어떤 문제는 문제에 주어진 정보가 너무 부족한 것 같은데도, 답을 알수 있다는 것이 놀랍고, 어떤 경우는 문제의 답들이 상식적인 예상을 벗어나는 놀라운 경우가 많았다. 

목차

추천의 글
서문
감사의 말

시커모어가에서의 살인 사건
수박을 거래하면서 생긴 일
그랜드캐니언의 흰머리 독수리 가족
농구 선수들의 조편성 속임수
월석 절도 미수 사건
듀보브 연구소의 보안 시스템
카지노에서 일어난 살인 사건
경주마 순위 매기기
볼링 평균 점수
필름 속 두 쇠공
샨카 화학약품회사에서 생긴 불운
퇴학당할 뻔하다
도심 속 숲
폭설이 내린 오크가의 아침

결론
찾아보기 - 문제와 관련하여
역자의 글

2016년 9월 15일 목요일

Brain teaser: Hand shakes

Q: Suppose you and your wife meet two other couples.  While greeting,  they shake hands with each other. (So, there are 6 people). But, a husband does not shake hands with his own wife.  After greeting, suppose you asks other people how many times did they hand shake. Surprisingly, all of them (5 people including your wife)  answers differently. In that case, what is the number of hand shakes of your wife?

    당신과 당신의 아내가 다른 2쌍의  부부를 만났다고 하자. (즉, 6명이 만났다.) 인사를 하면서 각자 악수를 한다음, 당신이 모두에게( 당신의 부인을 포함한 5명에게) 몇번이나 악수를 했는지 물었다고 하자.  단, 부부 끼리는 서로 악수를 하지 않는다. 놀랍게도 모두들 다른 숫자를 말했다고 한다면, 이 때 당신의 부인은 몇번 악수를 했을까?  (문제에 주어진 조건은 충분하다. )