71
ISBN XXX-XX-XXX-XXXX-X-XXXXX LAMMPS 기반 멀티스케일 모델링 Prototype(MD + SRD) 개발 보고서 2014. 11 국가슈퍼컴퓨팅연구소 슈퍼컴퓨팅융합연구센터 슈퍼컴퓨팅기술개발실

LAMMPS 기반 멀티스케일 모델링 · 2018. 10. 15. · LAMMPS 기반 멀티스케일 모델링 Prototype(MD + SRD) 개발 보고서 일 자: 2014년 11월 20일 부 서: 슈퍼컴퓨팅기술개발실

  • Upload
    others

  • View
    2

  • Download
    0

Embed Size (px)

Citation preview

  • ISBN XXX-XX-XXX-XXXX-X-XXXXX

    LAMMPS 기반 멀티스케일 모델링

    Prototype(MD + SRD) 개발 보고서

    2014. 11

    국가슈퍼컴퓨팅연구소

    슈퍼컴퓨팅융합연구센터

    슈퍼컴퓨팅기술개발실

  • LAMMPS 기반 멀티스케일 모델링

    Prototype(MD + SRD) 개발 보고서

    일 자: 2014년 11월 20일

    부 서: 슈퍼컴퓨팅기술개발실

    제출자: 차광호

  • 목 차

    1. 배경 …………………………………………………………………………………… 1

    1.1. 분자동역학 …………………………………………………………………… 1

    1.2. LAMMPS ……………………………………………………………………… 1

    2. LAMMPS 개요………………………………………………………………………… 3

    2.1. 배경 …………………………………………………………………………… 3

    2.2. 기본 구조 ……………………………………………………………………… 3

    2.3. 입력 데이터 구조……………………………………………………………… 4

    3. LAMMPS 동작 특성 ………………………………………………………………… 6

    3.1. LAMMPS 통신 구조 ………………………………………………………… 6

    3.2. LAMMPS의 문제 분할(Domain Decomposition) 방식 ………………… 7

    3.3. compute() 루틴 분석………………………………………………………… 8

    3.4. fix 기반의 기능 추가 ………………………………………………………… 9

    4. 단일 시스템에서의 LAMMPS 실행 특성………………………………………… 11

    4.1. 테스트베드 구성……………………………………………………………… 11

    4.2. 테스트베드의 메모리 시스템 특성………………………………………… 12

    4.3. LAMMPS의 메모리 접근 특성……………………………………………… 13

    4.4. LAMMPS의 병렬 성능 분석………………………………………………… 17

  • 5. LAMMPS 기반 MD+SRD 프로토타입 개발 ……………………………………… 22

    5.1. 개요 ………………………………………………………………………………… 22

    5.2. 식별자 인식 기반 MD+SRD 프로토타입 ……………………………………… 23

    5.3. 영역별 정보 전달 기반 MD+SRD 프로토타입 ……………………………… 30

    6. 결론 …………………………………………………………………………………… 35

    Appendix. A. MD+SRD 주요 소스 코드 …………………………………………… 38

    Appendix. B. LAMMPS 설치 ………………………………………………………… 58

    참고 문헌 ………………………………………………………………………………… 63

  • 표 목 차

    표 1. LAMMPS의 주요 클래스 구성 ………………………………………………… 4

    표 2. LAMMPS의 compute() 루틴[5] ……………………………………………… 9

    표 3. 테스트 베드 구성 ……………………………………………………………… 11

    표 4. 소프트웨어 구성 ………………………………………………………………… 11

    표 5. 시뮬레이션 구성 ………………………………………………………………… 12

    표 6. STREAM Benchmark 결과[14] ………………………………………………… 13

    표 7. MD 기법과 SRD 기법 비교 …………………………………………………… 22

    표 8. verlet::run() 기능의 의사코드[16] …………………………………………… 24

    표 9. MD+SRD 실행 테스트를 위한 입력스크립트 ……………………………… 26

    표 10. 성능 평가를 위한 시뮬레이션 구성 ………………………………………… 34

    표 11. 성능 평가를 위한 테스트베드 구성 ………………………………………… 34

    표 12. 성능 평가 결과 (단위:sec) …………………………………………………… 34

    표 13. fix_sbmd.h ……………………………………………………………………… 38

    표 14. fix_sbmd.cpp …………………………………………………………………… 40

  • 그 림 목 차

    그림 1. lammps.cpp 구조 ……………………………………………………………… 3

    그림 2. LAMMPS의 Forward_comm()과정………………………………………… 6

    그림 3. run 수행시 fix의 사용 과정 ………………………………………………… 10

    그림 4. 시뮬레이션 작업량의 구성 ………………………………………………… 12

    그림 5. compute()에서의 데이터 참조 지역성 특징 ……………………………… 14

    그림 6. compute()에서의 데이터 참조 범위 ……………………………………… 17

    그림 7. MPI와 OpenMP를 이용한 병렬 실행의 speedup ……………………… 18

    그림 8. Syetm III에서의 하이브리드 실행 결과 …………………………………… 19

    그림 9. Syetm II와 III의 수행 성능 비교 (16 프로세스 사용) ………………… 20

    그림 10. Syetm II와 III의 수행 성능 비교 (8 프로세스 사용) ………………… 20

    그림 11. MD+SRD 개념도 …………………………………………………………… 23

    그림 12. fix_mdsrd의 개념 모델 …………………………………………………… 23

    그림 13. fix_mdsrd를 위한 비트 마스크 …………………………………………… 26

    그림 14. 콜로이드 입자 + SRD 입자에 대한 혼합 시뮬레이션 예제 ………… 29

    그림 15. 영역별 정보 전달 기반의 fix_mdsrd 개념 모델 ……………………… 30

    그림 16. 통신 영역의 구성 …………………………………………………………… 31

    그림 17. MD빈과 SRD빈간 매핑테이블 예제 ……………………………………… 31

  • 그림 18. SRD에서 MD로의 통신을 위한 매핑테이블 …………………………… 32

    그림 19. MD에서 SRD로의 통신을 위한 매핑테이블 …………………………… 32

    그림 20. 3차원 쿠에트 흐름 시뮬레이션 구성 …………………………………… 33

    그림 21. 3차원 쿠에트 흐름의 속도 분포 ………………………………………… 33

  • - 1 -

    1. 배경

    1.1. 분자동역학

    분자 동역학은 고체, 액체나 기체 상태에서 분자들 간의 존재하는 힘에 의하여

    나타나는 분자들의 운동을 연구하여 해당 물질의 특성을 탐구하는 학문이다.

    분자 동역학은 1957년 Alder와 Wainwright에 의해 고안되어 Hard Sphere

    System에 대한 연구에 활용되었다[1,2].

    분자동역학이 소개될 당시에는 계산 자원의 한계로 인하여 작은 크기의 문제

    만 해석이 가능하였으나 컴퓨팅 자원에 대한 기술 발전은 보다 거대하면서도

    복잡한 문제들도 분자동역학으로 해석이 가능하도록 하였다. 또한 현재는 물리,

    화학, 생명과학 같은 서로 다른 분야의 다양한 문제들을 규명하는데 분자동역

    학이 널리 이용되고 있어 계산 과학 분야의 중요한 시뮬레이션 방법론으로 자

    리 매김하고 있다[1,2].

    개략적인 절차는 우선, 연구의 대상이 되는 물질을 구성하는 N개의 입자들에

    대한 운동 미분 방정식을 계산하여 각 입자들의 속도와 위치들을 구한다. 이

    과정을 반복적으로 수행하여 최종적으로 해당 물질의 여러 가지 물리적인 성질을

    파악하게 된다.

    대표적인 분자동역학 소프트웨어로는 CHARMM[3], AMBER[4], LAMMPS[5],

    NAMD[6]등이 있다. CHARMM과 AMBER는 오래 전부터 개발되어 잘 정의된 퍼

    텐셜 함수와 매개 변수들을 제공하지만 확장성에서는 제약이 있어서 백 여개의

    프로세스로 제한되는 단점이 있다. 반면 상대적으로 근래 개발된 LAMMPS와

    NAMD는 최근 HPC시스템의 아키텍쳐를 반영하여 확장성을 보장하는데 장점을

    가지고 있다.

    1.2. LAMMPS

    본 고에서 다루고자 하는 LAMMPS(Large-scale Atomic/Molecular Massively

    Parallel Simulator)는 앞서 설명한 분자동역학 시뮬레이션 소프트웨어 중 하나로

    대규모 해석이 가능한 병렬화된 분자동역학 코드이다. 1990년대 중반부터 미

    국 샌디아 연구소와 로렌스리버모어 연구소가 공동으로 개발하기 시작하여 현재는

    샌디아 연구소가 주도적으로 개발하고 있으며 오픈 소스 기반의 분자 동역학

    패키지 형태로 배포되고 있다[5,7].

    원자, 고분자, 생물학, 금속, 알갱이 및 coarse-grained system 등 다양한 분야의

  • - 2 -

    모델링이 가능하며 초기의 FORTRAN 버전을 지속적으로 발전시켜 현재는 객

    체 지향 언어인 C++ 언어로 작성되고 있다. 공간적인(spatial) 작업 분할 방식을

    따르고 있으며 기본적으로 MPI를 이용하여 병렬처리를 지원한다. 최신 HPC 아

    키텍쳐를 염두에 두고 개발되어 확장성이 우수하여 수 만개의 프로세서까지 활

    용이 가능하다[5,7].

  • - 3 -

    2. LAMMPS 개요

    2.1. 배경

    LAMMPS(Large-scale Atomic/Molecular Massively Parallel Simulator)의 구조적 특

    징을 개략적으로 정리하면 다음과 같다.

    객체 지향 언어인 C++을 사용하고 있으며 14개의 주요 클래스가 유기적으

    로 연동되어 동작한다.

    입력 스크립트 파일에 기술되는 주요 명령어와 직관적으로 연관된 `*.cpp'와

    `*.h'의 쌍으로 구성되어 있다.

    제3자에 의한 시스템 확장이 용이하도록 커맨드 방식이나 fix 방식의 프로

    그램 기능 추가를 지원하고 있다.

    기본적으로 사용되는 LAMMPS 실행 파일 이외에도 라이브러리 형태로 활용이

    가능하도록 기본적인 인터페이스를 제공하고 있다.

    2.2. 기본 구조

    그림 1은 LAMMPS의 기본 골격에 해당하는 `lammps.cpp' 파일의 구조를 보여준

    다. MPI를 이용한 병렬 프로세스들에 대한 초기화가 실행된 후 LAMMPS 객체가 생

    성되게 된다. 이후 파일 입력 처리 루틴을 통해 LAMMPS용 입력 스크립트를 순

    서대로 읽어가면서 환경 설정을 수행하고 시뮬레이션을 수행하게 된다.

    main

    MPI_Init

    lammps 객체 생성

    lammps->input->file();

    lammps 객체 제거

    MPI_Finalize

    그림 1. lammps.cpp 구조

    이와 같이 LAMMPS는 객체 지향 언어인 C++로 개발되어 있어서 표 1과 같이

    주요 개념 및 기능별로 14개의 클래스 정의가 되어 있다.

  • - 4 -

    표 1. LAMMPS의 주요 클래스 구성

    클래스명 기 능

    Input 입력 스크립트 파일을 읽어 변수 값 설정 또는 명령어 수행

    Output Thermodynamics 정보 출력 (화면, log 파일), snapshot, restart

    file 출력

    Error Error및 경고 메시지 출력

    Timer MPI 시간 정보 기록 및 출력

    Memory Vector와 array의 할당 관리, 새로운 객체들은 memory 클래스에

    정의된 함수에 의하여 생성됨

    Universe 병렬 작업을 위한 프로세스 별 partition 설정,

    MPI_Communicator 관리

    Comm 프로세스간의 통신과 ghost atom 관리

    Atom 모든 atom별 array 생성 및 데이터 관리

    Group Group 명령으로 구성된 atom group관리 및 group에 속한 atom

    들의 속성 관리

    Neighbor 모든 atom에 대한 neighbor 리스트를 생성하고 데이터 저장

    pair, fix, compute styles등에 의해 호출되고 각 명령어가 필요로

    하는 neighbor 리스트를 제공

    Domain Geometry 및 lattice에 관련된 정보 관리

    Force Atom들간의 Force 계산

    Modify Fix와 compute 클래스 관리

    Update Integrator(Verlet, rRESPA)와 energy minimizer 기능을 추상화한

    상위 클래스

    2.3. 입력 데이터 구조

    앞서 언급한 바와 같이 LAMMPS는 입력용 스크립트 파일을 차례대로 읽어서 각

    종 환경 설정용 변수 값을 설정하고 시뮬레이션 방법을 결정한 뒤 시뮬레이션

    을 수행하게 된다. 이때 사용되는 입력용 스크립트 파일은 크게 네 부분으로 구성되

    며 각 부분별 주요 기능을 살펴보면 다음과 같다.

    I. 초기화

    입자에 대한 정의 전에 초기화가 필요한 항목 기술

    역장(force field) 정의

  • - 5 -

    II. 원자 정의

    각 입자들의 위치 및 초기 값 설정(방법) 기술

    III. 시뮬레이션 설정

    역장 계수, 시뮬레이션 파라메터, 출력 방법

    fix들: 기존 계산 방법에 대한 변형 설정

    IV. 시뮬레이션 실행

    수행횟수(시뮬레이션 스텝)

  • - 6 -

    3. LAMMPS 동작 특성

    본 장에서는 병렬화된 LAMMPS가 수행하는 통신 유형을 살펴보고 병렬 수행을

    위해 필요로 하는 문제 분할 방식중 LAMMPS가 사용하고 있는 공간적 문제 분

    할 방식 방법과 주요 내부 루틴인 compute()에 대하여 좀 더 구체적으로 살펴

    보도록 한다.

    3.1. LAMMPS 통신 구조

    LAMMPS가 MPI를 이용한 병렬 수행이 가능해 지면서 어떠한 통신 방법을 주로

    사용하여 동작하는가에 대한 선행 연구들이 진행되었다[8,9]. 이를 바탕으로

    LAMMPS의 통신 특징을 살펴보면 MPI_Allreduce나 MPI_Bcast같은 집합 통신의

    의존도가 높음을 알 수 있다. 또한 그림 2와 같이 주변 프로세스들과 데이터를

    교환하기 위해서 forward_comm()이라는 일종의 halo exchange 과정을 빈번하게

    수행하고 있다.

    Old

    New

    Old

    New

    Old

    Old

    New

    Old

    New

    Old

    New

    Old

    Old

    New

    P5

    P1 P4

    P3

    P7

    P2

    P0 P6

    P8

    Old

    New

    Old

    New

    Old

    Old

    New

    Old

    New

    Old

    New

    Old

    Old

    New

    Old

    New

    Old

    New

    Old

    Old

    New

    Old

    New

    Old

    New

    Old

    Old

    New

    P5

    P1 P4

    P3

    P7

    P2

    P0 P6

    P8

    (a) (b)

  • - 7 -

    New

    NewNew

    New

    New

    New

    New

    Old

    New

    Old

    New

    New

    Old

    New

    Old

    New

    New

    Old

    New

    Old

    New

    New

    Old

    New

    Old

    New

    P5

    P1 P4

    P3

    P7

    P2

    P0 P6

    P8

    New

    New

    NewNew

    New New

    New

    NewNew

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    New

    P5

    P1 P4

    P3

    P7

    P2

    P0 P6

    P8

    (c) (d)

    그림 2. LAMMPS의 Forward_comm()과정

    3.2. LAMMPS의 문제 분할(Domain Decomposition) 방식

    LAMMPS는 풀고자 하는 문제(Domain)을 각 프로세스에게 할당하고자 할 때 전

    체 문제 영역을 균등하게 나누어 분배하는 공간 분할(Spatial Decomposition)방식을

    사용하고 있다. 이는 특정 공간에만 입자들이 몰려 있는 경우, 특정 프로세스에만

    계산량이 편중되는 부하의 불균형을 초래할 수 있으나1, LAMMPS는 이런 경우

    는 특히 이례적인 경우로 간주하여, 상대적으로 관리가 용이한 공간 분할 방식

    을 사용하고 있다.

    기본적으로 3차원 시뮬레이션 공간의 각축에 적당한 프로세스 수를 배치하여

    공간을 분할하게 되는데 surface-to-volume ratio를 최소화 할 수 있는 프로세스

    수의 조합을 선택하게 된다. 이와 같은 방법은 onelevel이라 표현하고 있으며

    최근에는 멀티 코어 환경을 고려하여 노드당 코어 수를 감안한 twolevel 방식의

    할당법도 사용되고 있다.

    X, Y와 Z를 각각 주어진 시뮬레이션 공간의 크기라고 하고 x, y 그리고 z를

    각축에 할당하고자 하는 프로세스의 수2라고 가정하면 surface-to-volume ratio

    는 다음의 식 (1)을 의미하며 이를 최소화하는 프로세스 조합을 사용하여 문제

    1 최신 버전 LAMMPS의 경우, 워크로드를 감안하여 도메인의 크기를 불균등하게 기술할 수

    도 있다.

    2 LAMMPS 수행을 위해 주어진 전체 프로세스의 수를 n이라고 하면 n=x·y·z를 만족해야 한다.

  • - 8 -

    분할을 수행한다.

    yz

    YZ

    xz

    XZ

    xy

    XY (1)

    이처럼 기본적으로 LAMMPS는 각 프로세스들이 도메인을 균등하게 분할하

    여 생성된 서브 도메인을 처리하는 방식이었으나 2013년 이후 버전의

    LAMMPS부터는 balance라는 커맨드와 fix를 제공하여 서브 도메인의 크기를

    사용자가 조절할 수 있도록 하였다. 커맨드 형의 balance는 정적으로 각 프로

    세스 별 서브 도메인의 크기를 지정하게 되고 fix형태의 balance를 사용하면

    동적으로 서브도메인의 크기 변경이 가능하다. 즉 이와 같은 기능을 이용하여

    시뮬레이션 공간에 입자들이 균등하게 존재한지 않는 경우에 대한 대처가 가

    능하게 되었다.

    3.3. compute() 루틴 분석

    LAMMPS에 대한 프로파일링 연구를 살펴보면 각 입자들간의 상호 작용하는 힘

    을 계산하는 과정에서 가장 많은 시간이 소요되며[10], 이웃 목록(neighbor list)

    과 내부 루프(inner loop)를 최적화하여 성능을 향상시킬 수 있다고 보고되고 있

    다[11]. 분자동역학적인 접근에서 입자간 상호 작용하는 힘은 일반적으로 레너

    드-존스 퍼텐셜(Lennard-Jones potential)과 같은 퍼텐셜 함수에 기반하여 계산

    된다. 즉 두 입자 i와 j간에 존재하는 에너지는 다음과 같은 레너드-존스 퍼텐

    셜로 기술될 수 있다.

    crrrr

    ru

    612

    4)(

    (2)

    이때 r은 두 입자간의 거리이고 rc는 컷 오프(cut off) 길이가 된다. 매개변수

    ε와 σ는 각각 상호 작용의 강도와 거리계를 의미한다[12][13]. 이를 바탕으로

    힘은 u(r)를 이용하여 다음과 같이 유도된다.

    f = -∇u(r) (3)

    LAMMPS의 compute() 루틴이 위의 계산을 수행하게 되며 표 2는 compute()

    루틴의 의사코드를 보여 주고 있다. 비록 pair 클래스 내에 여러 종류의

    compute() 루틴이 존재하기는 하지만, 일반적으로 힘과 에너지 등을 계산하기

    위하여 중첩된 루프 형태의 계산 루틴을 가지고 있다.

  • - 9 -

    표 2. LAMMPS의 compute() 루틴[5]

    1: procedure compute()

    2: for i = 0; i < inum; i++ do

    3: tmp = x[i]; // Get partcle i's location

    4: ...

    5: for j = 0; j < no. of i's neighbors; j++ do

    6: ...

    7: del = tmp - x[j];

    8: ...

    9: compute force_pair; // Use LJ potential

    10: ...

    11: f[i] += del x force_pair; // Update force

    12: if newton_pair then

    13: f[j] -= del x force_pair;

    14: end if

    15: ...

    16: compute potential energy; // Update energy

    17: ...

    18: end for

    19: ...

    20: end for

    21: end procedure

    3.4. fix 기반의 기능 추가

    앞서 2장에서 언급한 바와 같이 제3자에 의해 LAMMPS의 기본 요소에 기능의

    추가나 기존 기능의 변경이 가능한데 주로 fix를 통해 이와 같은 내용을 수행하게

    된다. 본 절에서는 LAMMPS의 fix가 어떤 과정으로 인식되어 동작하게 되는지

    를 살펴본다.

    fix는 2.3절에 언급된 바와 같이 계산 방법에 대한 선택 사항이나 전후 처리

    방법을 기술하는데 사용되는 명령어이며 다음과 같은 문법 구조를 가지고 있다.

    fix ID group-ID style [args]

    이때 ID는 해당 fix에 대한 식별자로 사용자가 부여하며, group-ID는 해당 fix를 적

  • - 10 -

    용할 입자들의 그룹을 의미한다. style은 fix에 의해 동작하게 될 함수를 의미

    하며 뒤에 나오는 args를 선택적으로 사용하게 된다. 해당 fix를 해제하고자 할 때

    는 unfix를 이용하게 된다.

    fix의 처리 절차는 다음과 같다. 입력 파일을 파싱하는 과정에서 fix가 인식되면

    LAMMPS는 해당 fix에서 사용하고자 하는 기능(style명)의 set_mask를 확인한다.

    해당 기능을 수행하는 함수를 포함하고 있는 객체는 해당 함수가 시뮬레이션

    과정의 어느 부분에서 수행되어야 하는지에 대한 정보를 mask 형태로 보유하

    고 있다. 즉 예를 들어 force를 계산하기 전인 modify->pre_neighbor 단계인지

    아니면 force를 계산한 뒤에 modify->post_force 과정에서 수행되어야 하는지에

    대한 정보가 이 mask에 기록되어 있다. 따라서 LAMMPS는 해당 fix의 ID를 수

    행되어야 할 단계의 함수 테이블에 등록한다. 이후 실제 시뮬레이션이 수행될 때3 각 단계의 함수 테이블에 등록된 fix들의 함수를 수행하게 된다. 그림 3은 이와

    같은 과정을 도식화 한 것이다.

    그림 3. run 수행시 fix의 사용 과정

    이처럼 fix는 run 시점에 참조되어 사용될 수 있도록 적절한 함수 테이블에

    해당 fix를 등록시켜는 역할을 하며 unfix는 이와 반대 절차로 해당 fix를 함수 테

    이블에서 해제하는 기능을 수행하게 된다.

    3 run 1000과 같이 run 명령어에 의해 n번의 반복 계산이 수행된다.

  • - 11 -

    4. 단일 시스템에서의 LAMMPS 실행 특성

    최근 하드웨어 시스템 기술의 발달로 대부분의 컴퓨터 시스템이 멀티 코어 기

    반의 프로세서를 사용하고 있으며 그 집적도 또한 급격히 증가하고 있다. 이는

    단일 시스템에서도 병렬성을 요구하는 프로그램들의 실행이 가능해지고 있다는

    의미로 해석될 수 있다. 본 장에서는 이러한 멀티 코어 시스템에서 분자 동역

    학 시뮬레이션 코드인 LAMMPS의 병렬 성능을 측정하고 분석하였다. LAMMPS

    를 이용하는 여러 가지 시뮬레이션을 MPI와 OpenMP를 활용하는 형태로 수행

    하여 멀티 코어 환경에서 어떤 병렬 효율성을 보여 주는지 확인하였다.

    4.1. 테스트베드 구성

    LAMMPS의 성능 측정을 위하여 3종류의 멀티코어 시스템을 사용하였다. 표 3은

    하드웨어적인 특징을 표 4는 소프트웨어적인 특징을 설명한다.

    표 3. 테스트 베드 구성

    System I System II System III

    CPU Intel Core i7-960

    3.20 GHz

    Intel Xeon X5650

    2.67 GHz

    Intel Xeon E5-2665

    2.40 GHz

    CPU 수 1 2 2

    CPU당 Core 수 4 6 8

    노드당 Core 수 4 12 16

    메모리 24 GB 24 GB 32 GB

    표 4. 소프트웨어 구성

    OS CentOS 6.3 (linux 2.6.32)

    Compiler Intel Compiler 13.0 (icc, icpc, ifort)

    MPI MPICH2 1.4.1p1

    LAMMPS Lammps-3Feb13

    FFT Fftw-2.1.5

    LAMMPS가 수행되면 입력 스크립트 파일을 해석하여 필요한 계산 방법론들

    을 선택적으로 사용하게 된다. 즉 분야별로 서로 다른 계산 방법들을 이용하기

    때문에 다양한 경우의 LAMMPS의 동작 특성을 파악하기 위하여 표 5와 같은 7

    종류의 시뮬레이션을 준비하였다. 같은 종류의 시뮬레이션에 대하여 작업 특성

    을 다르게 하여 LAMMPS의 병렬화 특성을 살펴보았다. LAMMPS의 작업량은 그

  • - 12 -

    림 4와 같이 시뮬레이션의 크기와 시뮬레이션 스텝에 의해 결정된다. 표 5의

    시뮬레이션 중 case I은 그림 4의 (a)와 같이 작은 크기의 시뮬레이션을 길게

    수행하는 경우를 case II는 (b)와 같이 좀더 큰 시뮬레이션을 보다 짧게 수행하

    는 경우의 구성을 준비하였다.

    표 5. 시뮬레이션 구성

    Case I Case II

    입자수 시뮬레이션

    스텝

    입자수 시뮬레이션 스텝

    colloid 용액과 콜로이드 입자를 MD로 해석

    900 100000 14400 10000

    crack 고체의 균열 해석 2071 100000 32281 10000

    flow(c) Couette 유동 해석 420 100000 6480 10000

    flow(p) Poiseuille 유동 해석 420 100000 6480 10000

    indent 고체의 패임 현상 해석 420 100000 6720 10000

    nemd 불균형 MD 해석 160 100000 2560 10000

    srd 용액과 콜로이드 입자를 SRD와 MD로 해석

    14716 100000 92013 10000

    Simulation Steps (time)

    Pro

    ble

    m S

    ize

    Simulation Steps (time)

    Pro

    ble

    m S

    ize

    (a) (b)

    그림 4. 시뮬레이션 작업량의 구성

    4.2. 테스트베드의 메모리 시스템 특성

    테스트베드로 쓰인 각 멀티코어 시스템의 메모리 성능을 확인하기 위하여

    STREAM 벤치마크[14]를 수행하였다. 이는 지속적인 메모리 접근 대역폭을 확

    인하는 것이 주목적인 벤치마크로서 부동 소숫점 연산과 메모리 접근이 혼합된

    형태의 테스트를 수행한다. 표 6은 각 시스템의 STREAM 벤치마크 결과를 보여

    준다. System III의 코어 수는 System II에 비해 4개가 많지만 속도 면에서는 낮

    은 클럭 주파수를 가지고 있다. 그러나 STREAM 벤치마크에 기초한 메모리 접

    근 성능은 대략 두 배 정도 우수한 것으로 나타나고 있다.

  • - 13 -

    표 6. STREAM Benchmark 결과[14]

    Copy (GB/s) Scale (GB/s) Add (GB/s) Traid (GB/s)

    System I 13.86 17.66 15.81 15.95

    System II 22.46 26.83 30.53 30.94

    System III 49.75 55.20 57.99 58.57

    4.3. LAMMPS의 메모리 접근 특성

    사용자 레벨의 어플리케이션인 LAMMPS의 메모리 접근 패턴을 가상 메모리 주

    소 환경에서 정확하게 파악하는 것이 어렵기는 하지만 우선 LAMMPS가 어떤

    패턴의 메모리 접근 요청을 생성하는가를 확인하는 것도 나름대로 의미가 있을

    것으로 예상되는 바이다. 이에 본 장에서는 LAMMPS의 주된 작업 과정인

    compute() 루틴의 메모리 접근 특성을 살펴보고자 한다. 표 2에서 보는 바와

    같이 입자들의 좌표 정보가 저장되어 있는 2차원 x행렬 4과 힘에 대한 정보가

    저장되어 있는 2차원 f행렬이 가장 빈번하게 사용되는 주된 변수들이다. 이러한

    행렬들이 어떤 순서로 접근되는지를 로그 파일 형태로 기록할 수 있도록

    LAMMPS를 수정하여 각 시뮬레이션들을 수행하였다.

    그림 5는 compute()를 수행하는 과정에서 접근되는 x[i][k]와 x[j][k]들의 x행렬

    로부터의 오프셋을 보여준다5. Cell list 기반의 verlet 알고리즘을 사용하는 분

    자동역학 프로그램의 경우, 표 2의 5번째 줄처럼 neighbor list를 유지하게 되는

    데 compute()루틴의 내부 루프에서 이 neighbor list를 탐색하게 된다. LAMMPS

    가 데이터 파일이나 restart파일을 읽어서 수행되는 경우가 아닌 경우에는 인접

    한 입자들은 동일한 neighbor list에 존재할 확률이 높다. 하지만 시간이 흐름에

    따라 입자들이 이동하게 되고 neighbor list에 대한 빈번한 수정이 필요로 하게

    된다. 그림 5는 이와 같은 상황을 잘 보여 주고 있다. 즉 시뮬레이션 초기인 ts

    = 1000인 경우, x 행렬에 저장된 인접한 입자들은 공간적으로도 근접한 입자들

    이고 서로의 neighbor list에 위치할 확률이 높다. 그러나 시뮬레이션이 진행됨

    에 따라 입자들이 점점 위치를 변경하는 경우, 인접했던 입자들이 서로 다른

    neighbor list에 위치할 확률 또한 증가하게 된다. 이처럼 그림 5는 시뮬레이션

    초기에는 두 행렬에 존재하는 인접한 입자들을 참조하는 순차적인 접근과 비슷

    4 예를 들어 x[i][0], x[i][1] 과 x[i][2]는 i번째 입자의 x축, y축 그리고 z축 좌표를 각각 저장하

    게 된다.

    5 x와 f행렬은 compute()의 이중 루프 내에서 동일한 인덱스 i와 j를 사용하기 때문에 동일

    한 접근 패턴을 띄게 된다.

  • - 14 -

    한 패턴을 보이나 시간이 경과하면서 랜덤한 접근 형태를 보이게 된다.

  • - 15 -

    그림 5. compute()에서의 데이터 참조 지역성 특징

    그림 6은 시뮬레이션의 한 루프에서 접근되는 변수들의 논리적인 범위를 보

    여준다. 즉 각 시뮬레이션들 중에서 최대 64KB 범위 내의 변수들이 접근됨을

    확인할 수 있었다. 한 루프에서 접근되는 변수들의 범위는 neighbor list내에 존

    재하는 입자들의 수와 무관하지 않는데 colloid의 경우 접근 범위가 시간에 따

    라 증가함을 볼 수 있다. 즉, colloid 시뮬레이션의 경우, time integration을 위

    하여 npt fix를 사용하는데 이 fix는 시뮬레이션 박스의 크기를 축소시키는 결과

    를 야기한다. 따라서 각 neighbor list들에 존재하는 입자들의 수가 증가하게 되

    어 최종적으로 한 루프에서 접근되는 입자들의 수가 증가함을 유추할 수 있다.

  • - 16 -

  • - 17 -

    그림 6. compute()에서의 데이터 참조 범위, 16개의 프로세스를 사용하여 로그

    를 생성함.

    4.4. LAMMPS의 병렬 성능 분석

    4.4.1. MPI와 OpenMP 성능 비교

    앞서 설명한 7종류의 시뮬레이션에 대하여 각 시스템에서의 병렬 수행 성능을

    분석하였다. LAMMPS가 기본적으로 사용하는 병렬 실행 환경인 MPI 이 외에

    단일 시스템에서 좀 더 경량화된 병렬 수행이 가능한 OpenMP를 사용하여

    LAMMPS를 실행하였다. LAMMPS 자체 패케지에는 OpenMP 기능이 존재하지 않

    기 때문에 LAMMPS와 같이 배포되고 있는 OpenMP용 추가 패케지인

    USER_OMP[15]를 설치하여 OpenMP 실행이 가능한 LAMMPS를 구성하였다. 각

    시스템이 하이퍼쓰레딩을 지원하는 인텔 CPU를 장착하고 있음을 감안하여 MPI

    나 OpenMP를 위한 프로세스나 쓰레드 수는 물리적인 코어 수의 두 배 이상까

    지 설정하여 병렬 성능을 측정하였다. 그림 7은 각 병렬화 방법에 의해 나타나

    는 speedup를 기록한 것이다.

  • - 18 -

    (a) Case I에 대한 MPI 실행 (b) Case I에 대한 OpenMP 실행

    (c) Case II에 대한 MPI 실행 (d) Case II에 대한 OpenMP 실행

    그림 7. MPI와 OpenMP를 이용한 병렬 실행의 speedup. 각 그래프에서 빨간색

    화살표는 해당시스템의 물리적인 코어 수를 의미한다.

    단일 시스템에서 테스트를 수행하였음에도 MPI를 사용한 병렬 수행의 효과가

    OpenMP를 사용하였을 때 보다 더 큰 것으로 나타났다. 이는 LAMMPS가 각 시

    뮬레이션의 대상인 각 입자들을 분할하여 병렬 처리하는 것이 아니라 시뮬레이

    션 공간을 분할하는 방식을 취하기 때문에 OpenMP 방식이 적합하지 않을 수

    있다는 선행 연구 결과들과 같은 맥락이라 할 수 있다[15].

    또한 LAMMPS가 기본적으로 메세지 전달 방식의 병렬 프로그래밍 기법을 감

    안하여 설계되어 있어서 루프 레벨 병렬화를 주로 고려한 LAMMPS용 OpenMP

    패케지가 성능을 개선시키기에는 한계가 있는 것으로 풀이된다. 즉 MPI 기반

    의 LAMMPS 프로세스는 도메인 분할에 의해 쪼개어진 시뮬레이션 공간을 할당

    받아 실행이 되는 반면 OpenMP 기반의 LAMMPS는 표 2의 두번째 라인에 해당

    하는 가장 외부 루프의 병렬화를 수행하게 된다. 즉 서로 접근 방식에는 차이

    가 있으나 compute()루틴에서 수행되는 작업을 병렬처리 하고자 한다는 점에서

    공통점을 찾을 수 있다. 그러나 실험 결과에서 보듯이 도메인 분할 없이 단순

  • - 19 -

    히 루프레벨의 병렬화를 통해서만 성능 향상을 꾀하기에는 한계가 있음을 확인

    할 수 있다.

    또한, 수행 시간의 대략적인 프로파일링이 가능한 timer 객체가 생성하는 로

    그 파일을 살펴보면 MPI를 이용하는 경우, 통신 시간이 더 많이 필요한 것은

    사실이나 LAMMPS의 실질적인 주요 루틴인 compute()에서는 OpemMP보다 훨씬

    짧은 시간이 소요됨을 확인할 수 있었다.

    이처럼 모든 실험에서 OpenMP를 이용한 경우, MPI를 이용했을 때 보다 하회

    하는 성능을 보였고 특히 OpenMP 버전이 제공되지 않고 있는 SRD 시뮬레이션

    이 OpenMP를 이용하는 경우에는 오히려 성능이 저하되는 결과만을 보였다.

    Case I의 경우, 두 시스템 모두 물리적인 코어 수와 비슷한 숫자의 프로세스

    (또는 쓰레드)를 사용하는 경우에 가장 좋은 성능을 보여주었고 문제의 크기가

    큰 case II의 경우, 좀 더 많은 프로세스 수까지 병렬성이 증가되거나 성능 개선

    정도가 더 향상됨을 확인할 수 있었다.

    MPI와 OpenMP를 혼합하여 실행하는 하이브리드 기법에 대한 성능 측정도

    진행하였다. 앞선 실험에서 가장 좋은 성능을 보였던 프로세스 수6를 MPI 프로

    세스와 OpenMP 쓰레드 수로 조합하여 성능을 측정하였다. System I 과 System

    II의 결과 모두 MPI만을 이용하는 경우의 성능이 가장 우수한 것으로 나타났다.

    반면 그림 8에 보이는 System III의 결과처럼 crack과 같은 일부 시뮬레이션에

    서는 MPI와 OpenMP를 함께 사용하는 것이 좋은 결과를 보이는 경우도 있기는

    했으나 대부분의 경우 MPI만 단독으로 사용하는 경우가 더 바람직한 성능을 보

    이는 것으로 확인되었다.

    (a) System III에서 Case I 실행 (b) System III에서 Case II 실행

    그림 8. Syetm III에서의 하이브리드 실행 결과.

    6 System I은 4. System II와 System III는 각각 16개의 프로세스를 사용할 때 가장 좋은 병렬

    성능을 보였다.

  • - 20 -

    4.4.2. System II와 System III 성능 비교

    앞서 설명된 각 테스트 베드 중 System II와 System III는 두 개 CPU를 가지고

    있는 NUMA 아키텍쳐 방식을 취하고 있다. 이에 두 시스템에서의 성능 차이를

    비교해 볼 필요가 있다. 앞서 메모리 성능을 확인하는 과정에서 언급된

    STREAM 벤치마크의 결과를 되새겨 보면, system III의 CPU 코어 속도가

    system II 보다 느리기는 했지만 메모리 성능은 크게 두 배 가까이 좋은 것으로

    나타났다. 그림 9와 같이 16개의 프로세스를 사용하는 LAMMPS 성능을 비교하

    여 두 시스템을 비교해 보면 case I을 푸는 경우에는 System III가 최대 27.3%까

    지 우수한 성능을 보였고 case II를 푸는 경우에도 최대 39.4%까지 실행 시간이

    단축됨을 확인할 수 있었다. 이는 System III가 보다 많은 물리적 코어를 제공한

    다는 점7에서 그 이유를 찾을 수도 있지만, 우수한 메모리 시스템의 성능도 무

    시할 수는 없을 것으로 예상되는 부분이다.

    (a) Case I 결과 (b) Case II 결과

    그림 9. Syetm II와 III의 수행 성능 비교 (16 프로세스 사용)

    (a) Case I 결과 (b) Case II 결과

    그림 10. Syetm II와 III의 수행 성능 비교 (8 프로세스 사용)

    7 그림 10과 같이 System II와 System III 모두의 물리적인 코어 수 보다 적은 8개의 프로세

    스를 사용하는 경우에도 System III가 좋은 성능을 보이고 있는 점은 그림 9에서 system II가

    물리적 코어보다 많은 프로세스를 사용해서 나타난 결과라고 단정 짓기에는 무리가 있다.

  • - 21 -

    이상의 실험 결과를 바탕으로 단일 노드에서는 OpenMP의 사용이 무의미하며

    MPI를 사용하는 것이 병렬성을 향상시키는데 도움이 된다는 것을 확인할 수 있

    었다. 다만 많은 노드들을 사용하는 클러스터 시스템에서 일정수의 노드가 넘

    어 가면서 나타날 수 있는 노드간 통신 비용의 급증을 해결하기에는 OpenMP와

    MPI의 혼합된 사용이 적절한 방법이 될 것으로 예상되는 바이다.

  • - 22 -

    5. LAMMPS 기반 MD+SRD 프로토타입 개발

    본 장에서는 LAMMPS기반의 멀티스케일 모델링을 위한 프로토타입의 설계 과

    정을 설명한다. 메조스코픽 시뮬레이션 방법론인 SRD(Stochastic Rotation

    Dynamics)를 분자 동역학 방법론과 결합하여 멀티스케일 시뮬레이션 프로토타

    입을 구성하였으며 LAMMPS의 외부 확장용 인터페이스인 fix 형태로 개발되었

    다.

    5.1. 개요

    본 고에서 설명하고자 하는 멀티스케일 모델링 기법은 표 7과 같이, 나노(nano)

    또는 마이크로 스케일(micro-scale)의 계산이 가능한 분자 동역학과 열적 요동

    및 Hydrodynamics 상호 작용을 모두 고려할 수 있는 메조스코픽 스케일

    (Mesoscopic scale)의 시뮬레이션 방법인 SRD를 결합하는 것을 목표로 한다.

    표 7. MD 기법과 SRD 기법 비교

    장 점 단 점

    MD - 경계 근처의 물성을 정확하게

    계산 가능

    - Hydrodynamics 상호 작용을

    고려할 수 없음

    SRD - Hydrodynamics 를 고려한

    문제의 시뮬레이션에 적합

    - 경계 근처에서의 정확한 물성

    계산이 불가능함

    현재 LAMMPS는 추가 페케지의 형태로 SRD 기능을 제공하고 있는데 특정 입

    자들에 대해서만 고전적인 MD 계산을 적용하고 다수의 입자들에는 MD 계산

    대신 SRD 기법을 적용하고 있다. 매 시뮬레이션 스텝마다 적용해야 하는 MD

    계산 대신, 보다 긴 주기로 수행되는 SRD 계산을 다수에 입자에 적용함으로서

    전체 계산량을 줄일 수 있다는 장점이 있으며 콜로이드와 같은 물질의 해석에

    사용되고 있다.

    그러나 LAMMPS가 제공하는 SRD 패케지는 입자들의 종류에 따라 계산 모델

    을 변경하는 방식으로 경계면과 같은 영역별로 해석 방법을 변경할 수 없는 제

    약이 따른다.

    본 연구에서는 그림 11과 같이 LAMMPS의 SRD 패케지를 발전시켜 특정 입자

    들에만 MD 계산을 적용하는 것이 아니라 특정 영역에도 MD 계산이 가능하도

    록 하여 다루는 계의 물성을 보다 정확하게 계산하고자 한다.

  • - 23 -

    그림 11. MD+SRD 개념도

    5.2. 식별자 인식 기반 MD+SRD 프로토타입

    5.2.1. 식별자 인식 기반의 fix_mdsrd 개요

    제안하고자 하는 MD+SRD 프로토타입의 목표는 그림 12와 같이 경계 영역의

    SRD 입자들을 시뮬레이션 할 때 분자동역학 기법을 적용하는 것이다. 구현에

    있어서 주된 고려 사항은 SRD 입자들의 위치에 따라 시뮬레이션 방법론이 바

    뀌어야 하므로 입자들의 위치를 주기적으로 파악하는데 있다. 이러한 문제를

    효율적으로 해결하기 위하여 LAMMPS의 인터페이스 기술을 확인하였고 결과적

    으로 fix 형태의 구현을 시도하였다.

    MD zone overlap zone SRD zoneBoundary

    non-SRD particle

    SRD particle

    ..1001011

    ..0010101

    ..1001011

    ..0001011

    ..0011001

    ..0111001

    ..0110001

    그림 12. 식별자 인식 기반의 fix_mdsrd 개념 모델

  • - 24 -

    표 8. verlet::run() 기능의 의사코드[16]

    1: for loop over N timesteps do

    2: ev_set()

    3: ...

    4: fix->initial_integrate()

    5: fix->post_integrate()

    6: ...

    7: nflag = neighbor->decide()

    8: if nflag then

    9: fix->pre_exchange()

    10: domain->pbc()

    11: domain->reset_box()

    12: comm->setup()

    13: neighbor->setup_bins()

    14: comm->exchange()

    15: comm->borders()

    16: fix->pre_neighbor()

    17: neighbor->build()

    18: else

    19: comm->forward_comm()

    20: end if

    21: ...

    22: force_clear()

    23: fix->pre_force()

    24: ...

    25: pair->compute()

    26: bond->compute()

    27: angle->compute()

    28: dihedral->compute()

    29: improper->compute()

    30: kspace->compute()

    31: ...

    32: comm->reverse_comm()

    33: ...

    34: fix->post_force()

    35: fix->final_integrate()

    36: fix->end_of_step()

    37: ...

    38: if any output on this step: output->write()

    39: ...

    40: end for

  • - 25 -

    LAMMPS는 시뮬레이션 요소의 특성을 변경할 수 있는 fix라는 보조적인 연산

    을 제공한다. 표 8은 분자동역학 시뮬레이션 중 잘 알려진 시간 적분 방법인

    verlet 알고리즘의 run 명령어의 의사 코드이다. 각 시간 스텝에서 다양한 계산

    루틴들이 호출되며, 특히, 4, 5, 9, 16, 23, 34, 35, 36라인에서는 fix를 위해 등록

    된 루틴들이 호출된다8. 이처럼 fix 루틴은 한번의 time step을 처리하는 과정에

    서 수행되므로 시뮬레이션의 미세한 조정이 가능하다는 장점이 있다. 이런 이

    유로 MD+SRD 프로토타입을 fix를 이용하는 형태로 구현하였다.

    MD나 SRD 기법이 적용되어야 하는 영역에 대한 정보를 fix-mdsrd의 파라메

    터에 기술하도록 하여 LAMMPS에 전달 하도록 하였다. 이때 서로 다른 두 방법

    론을 심리스(seamless)하게 연결하기 위하여 오버랩 영역으로 이름 붙여진 하이

    브리드한 영역을 유지하도록 하였다. 즉 MD 영역에 존재하는 모든 입자들은

    오버랩 영역에 존재하는 SRD 입자들을 비 SRD 입자 즉 MD 입자로 간주하도록

    하였고 반면 오버랩 영역과 SRD 영역에 존재하는 입자들은 SRD 입자들을 있는

    그대로 간주하고 시뮬레이션을 수행하도록 하였다. 이처럼 입자들이 속한 영역

    에 따라 상대 입자들을 서로 다른 방식으로 간주하고 시뮬레이션을 수행해야

    하는 제약이 따른다. 이와 같은 내용을 포함하기 위하여 LAMMPS에서 사용되고

    있는 멤버쉽 관리를 차용하였다. LAMMPS의 비트마스크를 활용하여 각 영역에

    존재하는 입자들을 구분 할 수 있도록 하였다. 이에 대한 자세한 설명은 다음

    절에 기술된다.

    5.2.2. 비트 마스크 구조

    이처럼 fix_mdsrd에서는 각 입자들이 어느 영역에 위치하는가에 따라 적용되는

    시뮬레이션 방법이 결정되므로 영역별로 속해있는 입자들에 대한 정보가 필요

    하다. 기존의 LAMMPS에서는 각 입자에 대한 그룹 관리를 위해 비트 마스크를

    사용하고 있는데 fix_mdsrd를 수행하는 과정에서 필요한 입자들에 대한 식별자

    를 이 비트 마스크에 포함시켰다. 현재 fix_mdsrd에서 사용되고 있는 식별자들

    은 다음과 같다.

    mdgroup: MD 계산이 적용되어야 하는 입자들로서 비SRD입자와 MD

    zone과 overlap zone에 속한 SRD 입자들을 표시한다.

    shadow: SRD 입자들이 overlap zone이나 MD zone에 편입되는 과정

    (그림 12의 ①,②)에서 SRD입자임을 나타내는 식별 정보가 없어지게

    8 현재 개발된 프로토타입은 4, 5, 23, 34, 35, 36라인의 fix함수를 수행하는 과정에서 호출된

    다.

  • - 26 -

    된다. 이후 이 입자들이 SRD zone으로 돌아 올 때(그림 12의 ④), 과

    거에 SRD 입자였음은 알려주는 기능을 담당한다.

    ovsrd: overlap zone에 속한 SRD 입자의 경우, MD 계산을 선택적으로

    적용하는 특징이 있어서 mdgroup 이외에 별도 관리가 필요하다. 이

    를 위한 식별자가 ovsrd이다.

    inbig: ovsrd에 속한 SRD 입자의 계산 방식에 따라 overlap zone과

    SRD zone의 비SRD입자들의 계산값이 보정되어야 하다. 이를 위해

    overlap zone과 SRD zone의 비SRD입자들을 식별하기 위한 정보가 필

    요하다.

    inbig ovsrd shadow mdgroup small big all...

    high low

    32 bits

    그림 13. fix_mdsrd를 위한 비트 마스크

    이와 같은 4개의 비트는 한 타임 스템을 처리하면서 주기적으로 업데이트 된

    다. 우선 fix_mdsrd를 위한 4개의 비트들은 매 반복의 처음 부분(fix→

    initial_integrate)에서 업데이트 된다. 그 후, 오버랩 영역에 있는 SRD 입자들의

    mdgroup 비트가 선택적으로 force 계산 전후(fix→pre_force 또는 fix→

    post_force)에 업데이트되어 사용된다.

    5.2.3. 실행테스트

    MD+SRD 프로토타입의 테스트를 위하여 표 9와 같은 스크립트를 이용하여 콜로

    이드 입자와 SRD입자가 혼합된 형태의 시뮬레이션을 수행하였다.

    표 9. MD+SRD 실행 테스트를 위한 입력스크립트

    # 2d SRD test: big + small particles

    units lj

    atom_style sphere

    atom_modify first big

    dimension 2

    boundary f f p

    # create big particles with sigma 1.0

    lattice sq 0.4

  • - 27 -

    region box block 0 10 0 10 -0.5 0.5

    create_box 3 box

    region bigbox block 0.2 9.8 0.2 9.8 -0.5 0.5

    create_atoms 1 region bigbox

    set type 1 mass 1.0

    set type 1 diameter 1.0

    group big type 1

    velocity big create 1.44 87287 loop geom

    # equilibrate big particles

    pair_style lj/cut 2.5

    pair_coeff 1 1 1.0 1.0

    pair_coeff 2 2 0.0 1.0 0.0

    pair_coeff 1 2 0.0 1.0 0.0

    pair_coeff 1 3 1.0 0.6

    pair_coeff 2 3 1.0 0.2

    pair_coeff 3 3 1.0 0.2

    neighbor 0.3 bin

    neigh_modify delay 0 every 1 check yes

    fix 1 big nve

    fix 2 all enforce2d

    fix 3 all wall/region box lj126 1.0 1.0 2.5

    run 1000

    unfix 1

    unfix 2

    unfix 3

    # add small particles as hi density lattice

    lattice sq 0.4

    region plane block 0.2 9.8 0.2 9.8 -0.001 0.001

    lattice sq 85.0

    create_atoms 2 region plane

    set type 2 mass 0.01

    set type 2 diameter 0.0

    group small type 2

    velocity small create 1.0 593849 loop geom

    pair_style lj/cut 2.5

    pair_coeff 1 1 1.0 1.0

    pair_coeff 2 2 0.0 1.0 0.0

    pair_coeff 1 2 0.0 1.0 0.5

    pair_coeff 1 3 1.0 0.6

    pair_coeff 2 3 1.0 0.2

    pair_coeff 3 3 1.0 0.2

    delete_atoms overlap 0.5 small big

  • - 28 -

    # define virtual type for MD_zone

    set type 3 mass 0.01

    set type 3 diameter 0.2

    group mdzone_all type 3

    group mdzone_all union big

    atom_modify first mdzone_all

    # SRD run

    reset_timestep 0

    neighbor 0.3 bin

    neigh_modify delay 0 every 1 check yes

    communicate multi group mdzone_all vel yes

    neigh_modify include mdzone_all

    # no pairwise interactions with small particles

    pair_style lj/cut 2.5

    pair_coeff 1 1 1.0 1.0

    pair_coeff 2 2 0.0 1.0 0.0

    pair_coeff 1 2 0.0 1.0 0.0

    pair_coeff 1 3 1.0 0.6 2.0

    pair_coeff 2 3 0.0 0.2

    pair_coeff 3 3 1.0 0.2

    # use fix SRD to push small particles out from inside big ones

    timestep 0.001

    fix 1 small sbmd mdzone_all big 0.2 0.1 3 2

    fix 2 mdzone_all nve/limit 0.01

    fix 3 small srd 20 big 1.0 0.25 49894 &

    radius 0.88 search 0.2 collision slip inside ignore

    fix 5 mdzone_all wall/region box lj126 1.0 1.0 1.5

    fix 6 all enforce2d

    # diagnostics

    compute tbig big temp

    variable pebig equal pe*atoms/count(big)

    variable ebig equal etotal*atoms/count(big)

    thermo_style custom step temp f_3[7] etotal v_pebig v_ebig press &

    f_3[1] f_3[2] f_3[3] f_3[4] f_3[5] &

    f_3[6] f_3[8] f_3[9] f_3[10]

    thermo_modify temp tbig

    thermo 100

    dump 1 all atom 10 vdump2.lammpstrj

    run 3000

    그림 14는 fix_mdsrd를 이용하여 시뮬레이션을 수행하는 과정 중 일부를 보여주

    며, 각 영역별로 다른 시뮬레이션 기법이 적용됨을 확인할 수 있었다.

  • - 29 -

    MD zone

    overlap zone

    SRD zone

    그림 14. 콜로이드 입자 + SRD 입자에 대한 혼합 시뮬레이션 예제:

    각 영역별로 다른 시뮬레이션이 방법이 적용되었음.

  • - 30 -

    5.3. 영역별 정보 전달 기반 MD+SRD 프로토타입

    앞서 설명된 프로토타입은 각 영역별로 서로 다른 해석 기법이 적용될 수 있다

    는 점을 보여주기에는 문제가 없으나 SRD입자를 MD입자로 간주하는 과정에서

    물리량의 변화가 발생하는 취약점을 가지고 있다.

    이에, 심리스한 시뮬레이션을 위하여 1차 프로토타입을 수정하여 일부 중첩

    영역에서 정보 전달이 가능하도록 하였다. 본 절에서는 이러한 정보전달 기반

    의 fix_mdsrd의 개요 및 구조에 대하여 설명한다.

    5.3.1. 영역별 정보 전달 기반의 fix_mdsrd 개요

    그림 15는 영역별 정보 전달 기반 fix_mdsrd의 기본 개념을 보여준다. 이전 방

    식과 달리 중첩 영역에 MD입자와 SRD 입자가 공존하나, 서로의 존재를 인식하

    지 못한 상황에서 시뮬레이션을 수행하게 된다. 이후 일정 시간을 주기로 특정

    영역에서 정보 교환을 수행하게 된다.

    MD zone

    SRD zoneBoundary

    MD particle

    SRD particle

    overlap zone

    Comm. zone: SRD to MD

    Comm. zone: MD to SRD

    그림 15. 영역별 정보 전달 기반의 fix_mdsrd 개념 모델

    MD와 SRD 방법론 모두 다루는 입자들을 빈(bin) 단위로 그룹지어 관리하므

    로 빈(또는 셀)단위의 평균 물리량을 전달하거나 참조하는 방식을 고려하였다.

    또한 그림 16과 같이 일반적으로 MD용 빈이 SRD용 빈보다 크게 형성되므로

    하나의 MD용 빈에 다수의 SRD용 빈들이 대응된다는 가정하에 MD에서 SRD,

    SRD에서 MD로의 매핑테이블을 구성하여 정보 교환에 활용하였다. 두 통신 영

    역이 인접하는 경우, 넘겨준 정보가 받아야 하는 정보에 영향을 주는 일종의

    피드백 현상이 발생할 수 있으므로 충분한 공간을 두고 두 통신 영역을 설정할

  • - 31 -

    수 있도록 프로토타입을 구성하였다.

    SRD bins

    MD bin

    SRD bins

    MD bin

    그림 16. 통신 영역의 구성

    5.3.2. 정보 전달을 위한 매핑테이블 구성

    앞서 설명된 바와 같이 영역별 정보 전달 기반 mdsrd의 가장 핵심이 되는 부분

    은 중첩내의 통신 영역에서의 MD빈과 SRD빈의 대응관계를 확인하는 부분이다.

    그림 17과 같이 입력 파라메터에 기술된 각 통신 영역의 위치를 사용하여 해당

    영역에 존재하는 MD빈들의 목록을 확보한 뒤, 각각의 MD빈의 위치에 대응하는

    SRD빈들을 확인한다. 이는 일반적을 MD빈이 SRD빈 보다 큰 상황을 감안한 결

    과이다.

    ov

    erlap

    zon

    e

    MD

    SR

    D

    32 33 34

    23 24 25

    14 15 16

    ...

    ...

    ...

    ...

    ...

    ...

    93 94 95

    82 83 84

    71 72 73

    ...

    ...

    ...

    ...

    ...

    ...

    ji k... ...

    ts u... ...

    SRD to MD

    MD to SRD

    MD binsSRD bins

    overlap zone

    MD

    SRD

    그림 17. MD빈과 SRD빈간 매핑테이블 예제

  • - 32 -

    각 통신의 방향(MD에서 SRD, SRD에서 MD)에 따라 그림 18, 19와 같이 두

    종류의 매핑테이블을 사용하였다. SRD에서 MD로 통신은 각 SRD빈들의 평균값

    을 MD빈에 반영하는 과정에서 필요하다. 즉, t번째 MD빈에 대한 계산을 수행

    할, 각 SRD빈들의 평균이 필요하므로 그림 18과 같은 2차원 행렬을 참조하여

    해당 SRD빈들의 평균을 구하여 사용한다. 이때 첫번째 행의 값은 각 컬럼 즉,

    각 MD빈에 속한 SRD빈의 개수를 의미한다.

    반면 MD에서 SRD로의 통신은 SRD빈에 대한 물리량을 업데이트 할 때 대응

    하는 MD빈의 물리량을 반영하는 과정에서 나타난다. 특정 SRD빈이 어느 MD빈

    의 물리량을 확인해야 하는지를 그림 19와 같은 1차원 행렬로서 구현하였다.

    71

    72

    73

    94

    95

    9~

    Sp

    MD

    ~ ~

    .

    .

    .

    .

    .

    .

    .

    s t u... ...

    null

    null

    null

    (=n

    o. o

    f SR

    D b

    ins p

    er MD

    bin

    )

    m bins (= no. of MD bins)

    그림 18. SRD에서 MD로의 통신을 위한 매핑테이블

    n bins (= no. of SRD bins)

    j j j j j j j j j

    14 15 16 23 24 25 32 33 34... ...... ...

    ~ ~ ~ ~i i ik k k

    그림 19. MD에서 SRD로의 통신을 위한 매핑테이블

    5.3.3. 시뮬레이션 검증 및 성능테스트

    영역별 정보 전달 기반의 fix_mdsrd의 시뮬레이션 검증을 위하여 그림 20과 같

    이 3차원 쿠에트 흐름 시뮬레이션을 수행하였다. 그림과 같이 각 상·하판과 그

    판들과 인접한 영역은 MD입자로 가운데 부분은 SRD입자로 구성하였다. 즉, 상

    판의 움직임은 MD입자들에게만 직접적으로 전달되므로 상판의 움직임에 대한

    정보를 직접적으로 받을 수 없는 SRD입자들에게 MD입자들을 거쳐 물리량 정

    보가 얼마나 잘 전달되는지를 확인하는데 본 시뮬레이션의 목적이 있다.

    그림 21은 시뮬레이션 영역을 Y축 방향으로 균등하게 분할하여 각 영역에 존

    재하는 입자들의 평균 속도를 표시한 것이며 fix_mdsrd의 MD가 각 중첩 영역의

    중간부분까지 기존의 MD방법과 유사한 결과를 생성하였고 fix_mdsrd의 SRD 역

  • - 33 -

    시 가운데 부분을 시뮬레이션하는데 있어서 기존 방법과 유사한 해석 결과를

    생성한다는 사실을 보여주고 있다.

    그림 20. 3차원 쿠에트 흐름 시뮬레이션 구성

    그림 21. 3차원 쿠에트 흐름의 속도 분포

    fix_mdsrd의 실행 성능을 살펴보기 위하여 표 10과 같이 3차원 쿠에트 흐름

    을 3가지로 세분화하였다. 문제 크기와 입자 수를 서로 다르게 유지하였고 중

    첩 영역이 차지하는 비율 또한 다르게 설정하였다. 표 11과 같이 서로 다른 2

    종류의 테스트 베드를 실험에 사용하였다. 두 시스템 모두 공통된 소프트웨어

    를 사용하고 있으나 System II가 조금 많은 CPU 코어를 확보하고 있다.

  • - 34 -

    표 10. 성능 평가를 위한 시뮬레이션 구성

    Test I Test II Test III

    문제 크기 86 × 86 × 5 133 × 133 × 5 166 × 166 × 5

    중첩 영역 비율 0.61499 0.35836 0.31513

    입자 수 MD MDSRD MD MDSRD MD MDSRD

    MD 입자 수 147,920 117,820 353,780 171,570 551,120 210,820

    SRD 입자 수

    122,980

    315,210

    502,980

    표 11. 성능 평가를 위한 테스트베드 구성

    System I System II

    CPU Intel Xeon X5650 2.67GHz Intel Xeon E5-2665 2.40GHz

    CPU 수 2 2

    CPU 별 코어 수 6 8

    전체 코어 수 12 16

    OS CentOs 6.3 (linux 2.6.32)

    Compiler Intel Compiler 13.0

    MPI MPICH2 1.4.1p1

    FFT fftw-2.1.5

    표 12은 측정된 실행 시간을 정리한 것이다. 본 연구에서 개발된 fix_mdsrd는

    동일한 문제를 푸는 경우라고 하더라도 MD보다 많은 입자를 다루게 된다. 본

    실험에 사용된 테스트 집합 역시 표 10과 같이 fix_mdsrd가 다루게 되는 총 입

    자수가 MD보다 많다. Test I은 상대적으로 중첩영역이 많은 부분을 차지하나

    SRD 영역은 협소한 형태의 시뮬레이션으로 이와 같은 조건에서는 fix_mdsrd가

    중첩 영역을 계산하는데 많은 시간을 소모하여 오히려 MD보다 성능이 나빠진

    다. 반면 Test II 과 III는 SRD 영역을 증가시킨 경우로 두 시스템 모두

    fix_mdsrd가 수행시간을 단축시키는 것을 확인할 수 있었다.

    표 12. 성능 평가 결과 (단위:sec)

    System I System II

    MD MDSRD MD MDSRD

    Test I 2249.55 3912.97 1345.90 2073.86

    Test II 6384.36 5968.19 3405.29 3312.31

    Test III 10490.96 7845.75 5895.68 4592.46

  • - 35 -

    6. 결론

    LAMMPS는 범용 분자동역학 패케지로서 MPI를 이용한 병렬 수행을 지원함으로

    써 슈퍼컴퓨터를 활용하는 주요한 어플리케이션으로 자리 매김하고 있다. 본 고에서

    는 이러한 LAMMPS의 구조와 실행 특성을 살펴 보았다. LAMMPS는 MPI를 염두

    에 두고 설계된 이유로 병렬 확장성에 장점을 가지고 있다. 특히 시뮬레이션

    공간을 분할 방식의 공간 분할 방식을 취하고 있으며 최근 들어 추가적인 분할

    기법이 도입되어 균등 및 사용자 지정 분할이 가능해졌다.

    LAMMPS는 또한 시스템의 분야별 확장을 고려하여 제3자에 의한 시스템 수

    정이나 기능 추가가 용이한 구조를 가지고 있다. 우선 객체 지향 언어를 이용

    해 작성되어 기본 클래스를 기반으로 파생된 기능의 추가나 수정이 가능하며

    특히 LAMMPS가 정의한 fix 인터페이스 방법을 따라서 세부적인 기능 확장이

    가능하도록 되어있다. 또한 라이브러리화되어 사용될 수 있어서 사용자의 목적

    에 맞게 LAMMPS의 커스터마이징이 가능하다고 볼 수 있다.

    최근 증가 추세에 있는 멀티코어 기반 시스템 보급을 감안하여 멀티코어 시

    스템을 갖는 단일 시스템에서의 병렬화 성능을 분석하였다. LAMMPS의 가장 핵

    심이 되는 부분은 입자간의 작용하는 힘을 계산하는 루틴인데 이를 위해서는

    부동소숫점 연산이 못지 않게 빈번한 메모리 접근이 나타난다. 이때 생성되는

    메모리 접근 요청은 neighbor list내의 존재하는 입자들의 수와 물리적인 위치에

    주로 영향을 받게 되며 시뮬레이션이 진행됨에 따라 접근패턴에 변화가 나타나

    게 된다. 즉 메모리 서브시스템의 성능이 LAMMPS의 성능에 많은 영향을 미치

    게 되며 실험 결과 역시 메모리 시스템이 우수한 시스템에서의 LAMMPS성능이

    더욱 우수한 것으로 나타났다.

    다양한 병렬 수행 환경과 프로그래밍 언어들이 제공되고 있지만 아직까지 대

    표적인 순수 병렬처리 환경은 MPI와 OpenMP로 양분된다고 할 수 있다. 특히

    프로세스 보다는 경량화된 쓰레드 기반의 실행 특성을 감안하여 클러스터 시스

    템이나 분산 환경이 아닌 단일 시스템에서는 일반적으로 OpenMP가 주된 병렬

    화 방법으로 간주되고 있다. 이에 단일 시스템에서 LAMMPS 실행에 적합한 화

    경을 살펴 보았는데 LAMMPS의 기본 구조가 MPI에 적합한 형태로 설계되어 있

    어 OpenMP보다는 MPI가 LAMMPS에 더 효율적인 것으로 나타났다. 즉 MPI를

    사용하는 경우에는 공간 분할에 의해 나뉘어진 문제 영역을 대상으로 계산이

    수행되고 OpenMP를 사용하는 경우에는 문제 영역은 유지한 채로 루프 병렬화

    에만 의존하여 병렬 수행이 진행된다. 결국 MPI를 사용하는 LAMMPS의 경우,

    노드 내 프로세스간 통신에 의한 오버헤드가 존재하기는 하지만 계산 시간 만

    큼은 OpenMP 버전의 LAMMPS보다 훨씬 줄어 들어 전체 실행 시간도 더 짧게

  • - 36 -

    나타났다.

    이와 같은 OpenMP의 좋지 않은 결과에도 불구하고 OpenMP가 LAMMPS에

    항상 비효율적이지는 않을 것으로 예상된다. 즉, 클러스터 시스템 환경에서 MPI

    프로그램이 갖는 취약점 중 하나로 일정 규모의 이상의 노드들이 사용되는 경

    우에 나타나는 노드간 통신 오버헤드를 들 수 있다. 이런 경우에는 OpenMP의

    부분적이 사용으로 통신 오버헤드를 줄여 줄 수 있을 것으로 예상된다. 이러한

    상황을 종합적으로 고려해 보면, OpenMP는 단일 시스템에서 사용하기 보다는

    대규모 노드들이 사용되는 거대 규모 문제 해석시 MPI와 혼합된 형태로 사용하

    는 것이 훨씬 효율적일 것으로 예상되는 바이다.

    멀티스케일 모델링(Multi-Scale Modeling)은 여러 계산 과학 분야의 모델링 방

    법들을 선택적으로 조합하여 사용하는 것을 의미하는데 동일한 계산 자원을 이

    용하더라도 시뮬레이션 대상의 길이와 시뮬레이션 시간의 스케일이 확장 가능

    하다는 장점이 존재한다. 이와 같은 할당된 계산 자원의 효율적인 활용 이외에

    도 해석하고자 하는 문제 크기의 증대 및 보다 정확한 시뮬레이션 수행 등이

    가능하여 멀티 스케일 모델링에 대한 연구가 중요시되고 있다.

    본 고에서는 분자 동역학(Molecular Dynamics)과 유체 역학(Hydrodynamics)을

    결합하는 멀티스케일 모델링을 위한 프로토타입의 개발 과정을 소개하였다.

    SRD는 용제나 용액등의 특성을 유체 역학(Hydrodynamics)적인 방법으로 파악하

    며 콜로이드와 비SRD 입자가 포함된 혼합 문제의 경우에는 비SRD 입자만 분자

    동역학적인 방법으로 해석하게 된다. 이러한 SRD 방법론은 유체 역학

    (Hydrodynamics)적인 상호 작용을 모사하는데 적합하나 경계(Boundary) 근처에

    서의 정확한 물성 계산에는 한계가 있다고 볼 수 있다. 이에 본 연구에서는 비

    SRD 입자뿐만 아니라 경계 근처에서도 분자 동역학을 이용한 계산이 가능하도

    록 분자 동역학 기법과 SRD를 결합하는 내용의 멀티스케일 모델링을 구현하였

    다. 특히 제3자에 의한 수정이 용이한 fix구조로 두 종류의 프로토타입을 개발

    하였다.

    첫 번째 프로토타입에서는 각 입자에 식별자 정보를 부가하여 각 영역에 존

    재하는 입자별로 서로 다른 시뮬레이션 기법이 적용되도록 하였다. 각 시뮬레

    이션 영역의 입자 종류에 따라 적합한 시뮬레이션 기법이 선별되어 적용됨을

    확인함에는 문제가 없었으나 심리스한 시뮬레이션을 위해서는 모델링 기법의

    수정이 필요하였다.

    이에 두번째 프로토타입에서는 두 모델링 방법간에 정보 전달이 일어나는 영

    역을 정의하여 특정 MD빈과 SRD빈들간에 정보를 교환하는 방식으로 시뮬레이

    션의 정확도를 개선하였다. 시뮬레이션 결과 및 성능 검증 결과 기존의 MD방

    법만을 이용한 결과와 상당히 유사한 결과를 보이면서도 실행 시간은 크게 단

    축되었음을 확인할 수 있었다. 즉, SRD 방법론을 일부 차용하여 시뮬레이션 결

  • - 37 -

    과는 기존 MD방법과 유사하되 수행 시간은 기존의 MD방법 보다 우수하게 개

    선하자는 연구 목표에 부합되는 결과라고 할 수 있다.

  • - 38 -

    Appendix. A. MD+SRD 주요 소스 코드

    표 13. fix_sbmd.h

    #ifdef FIX_CLASS

    FixStyle(sbmd,FixSBMD)

    #else

    #ifndef LMP_FIX_SBMD_H

    #define LMP_FIX_SBMD_H

    #include "fix.h"

    namespace LAMMPS_NS {

    class FixSBMD : public Fix {

    public:

    FixSBMD(class LAMMPS *, int, char **);

    ~FixSBMD();

    int setmask();

    void init();

    void initial_integrate(int);

    void post_integrate();

    void pre_force(int);

    void post_force(int);

    void final_integrate();

    void end_of_step();

    void check_region();

    void check_reorder();

    void make_ovlist();

    void clone_grow(int);

    void backup_ov_srd(int);

    void restore_ov_srd(int);

    void backup_ov_big(int);

    void restore_ov_big(int);

    void backup_all(int);

    void restore_all(int);

    void swap_all(int);

    void ov_srd_on();

  • - 39 -

    void ov_srd_off();

    double memory_usage();

    int k_biggroup, k_biggroupbit;

    int k_mdgroup, k_mdgroupbit;

    int k_srdgroup, k_srdgroupbit;

    int ov_srdgroup, ov_srdgroupbit;

    int ov_biggroup, ov_biggroupbit;

    int in_biggroup, in_biggroupbit;

    int shadowgroup, shadowgroupbit;

    int nover;

    double ov_zone;

    double md_zone;

    int new_type, srd_type;

    int *newgroup1;

    int *newgroup2;

    int *newgroup3;

    double mdboxlo[3], mdboxhi[3];

    double overlaplo[3], overlaphi[3];

    int zone_change;

    double **clone_x, **clone_v, **clone_f;

    int nmaxclone;

    int novbig, novsrd, nmaxlocal;

    int *lovbig, *lovsrd;

    private:

    };

    }

    #endif

    #endif

  • - 40 -

    표 14. fix_sbmd.cpp

    #include "string.h"

    #include "stdlib.h"

    #include "fix_sbmd.h"

    #include "atom.h"

    #include "domain.h"

    #include "comm.h"

    #include "update.h"

    #include "integrate.h"

    #include "group.h"

    #include "force.h"

    #include "pair.h"

    #include "memory.h"

    #include "error.h"

    #define DELTA 1000

    #define NOV 0

    #define NOE 0

    using namespace LAMMPS_NS;

    using namespace FixConst;

    enum{X, V, F, ALL};

    /* ---------------------------------------------------------------------- */

    FixSBMD::FixSBMD(LAMMPS *lmp, int narg, char **arg) :

    Fix(lmp, narg, arg)

    {

    k_srdgroup = group->find(arg[1]);

    k_srdgroupbit = group->bitmask[k_srdgroup];

    k_mdgroup = group->find(arg[3]);

    k_mdgroupbit = group->bitmask[k_mdgroup];

    k_biggroup = group->find(arg[4]);

    k_biggroupbit = group->bitmask[k_biggroup];

    ov_zone = atof(arg[5]);

    md_zone = atof(arg[6]);

    new_type = atoi(arg[7]);

    srd_type = atoi(arg[8]);

    nevery = 1; // this is the value for end_of_step

    }

  • - 41 -

    /* ---------------------------------------------------------------------- */

    FixSBMD::~FixSBMD()

    {

    memory->destroy(clone_x);

    memory->destroy(clone_v);

    memory->destroy(clone_f);

    memory->destroy(lovbig);

    memory->destroy(lovsrd);

    }

    /* ---------------------------------------------------------------------- */

    int FixSBMD::setmask()

    {

    int mask = 0;

    mask |= INITIAL_INTEGRATE;

    mask |= POST_INTEGRATE;

    mask |= PRE_FORCE;

    mask |= POST_FORCE;

    mask |= FINAL_INTEGRATE;

    mask |= END_OF_STEP;

    return mask;

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::init()

    {

    int i,k;

    double box_length;

    double *myboxlo, *myboxhi;

    int dim = domain->dimension;

    int k_nlocal = atom->nlocal;

    double **x = atom->x;

    int *k_mask = atom->mask;

    char shadowname[] = "sbmd_shadow";

    char ov_srdname[] = "sbmd_ovsrd";

    char ov_bigname[] = "sbmd_ovbig";

    char in_bigname[] = "sbmd_inbig";

    double htemp, ltemp;

    double mdboxdiff[3], overlapdiff[3];

    nmaxclone = 0;

    clone_x = NULL;

    clone_v = NULL;

    clone_f = NULL;

  • - 42 -

    nmaxlocal = 0;

    lovbig = NULL;

    lovsrd = NULL;

    newgroup1 = NULL;

    newgroup2 = NULL;

    myboxlo = domain->sublo;

    myboxhi = domain->subhi;

    nmaxclone = k_nlocal;

    clone_grow(nmaxclone);

    nmaxlocal = k_nlocal;

    lovbig = memory->grow(lovbig,nmaxlocal,"fix_sbmd:lovbig");

    lovsrd = memory->grow(lovsrd,nmaxlocal,"fix_sbmd:lovsrd");

    memory->create(newgroup1,k_nlocal,"fix/sbmd:newgroup1");

    memory->create(newgroup2,k_nlocal,"fix/sbmd:newgroup2");

    memory->create(newgroup3,k_nlocal,"fix/sbmd:newgroup3");

    for(i=0; icreate(shadowname,newgroup1);

    shadowgroup = group->find(shadowname);

    shadowgroupbit = group->bitmask[shadowgroup];

    for(i=0; iboxhi[i] - domain->boxlo[i];

    overlaplo[i] = domain->boxlo[i] + (box_length * ov_zone);

    overlaphi[i] = domain->boxhi[i] - (box_length * ov_zone);

    mdboxlo[i] = domain->boxlo[i] + (box_length * md_zone);

    mdboxhi[i] = domain->boxhi[i] - (box_length * md_zone);

    }

    for(i=0; i

  • - 43 -

    newgroup3[i] = 0;

    for(k=0; kcreate(ov_srdname,newgroup1);

    ov_srdgroup = group->find(ov_srdname);

  • - 44 -

    ov_srdgroupbit = group->bitmask[ov_srdgroup];

    group->create(ov_bigname,newgroup2);

    ov_biggroup = group->find(ov_bigname);

    ov_biggroupbit = group->bitmask[ov_biggroup];

    group->create(in_bigname,newgroup3);

    in_biggroup = group->find(in_bigname);

    in_biggroupbit = group->bitmask[in_biggroup];

    memory->destroy(newgroup1);

    memory->destroy(newgroup2);

    memory->destroy(newgroup3);

    next_reneighbor = -1;

    check_region();

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::initial_integrate(int vflag)

    {

    int jflag;

    int k_nlocal = atom->nlocal;

    check_region();

    if(nmaxclone < k_nlocal) clone_grow(0);

    jflag = ALL;

    backup_ov_srd( jflag);

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::post_integrate()

    {

    int jflag;

    jflag = ALL;

    restore_ov_srd( jflag);

    ov_srd_on();

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::pre_force(int vflag)

    {

  • - 45 -

    int jflag;

    int k_nlocal = atom->nlocal;

    make_ovlist();

    if(nmaxclone < k_nlocal) clone_grow(0);

    jflag = ALL;

    backup_all( jflag);

    ov_srd_on();

    force->pair->compute(NOE,NOV);

    swap_all( jflag);

    backup_ov_srd( jflag);

    ov_srd_off();

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::post_force(int vflag)

    {

    int jflag;

    jflag = ALL;

    restore_ov_big( jflag);

    restore_ov_srd( jflag);

    ov_srd_on();

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::final_integrate()

    {

    int jflag;

    int k_nlocal = atom->nlocal;

    if(nmaxclone < k_nlocal) clone_grow(0);

    jflag = ALL;

    backup_ov_srd( jflag);

    ov_srd_off();

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::end_of_step()

    {

    int jflag;

  • - 46 -

    jflag = ALL;

    restore_ov_srd( jflag);

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::check_region()

    {

    int i,j,k;

    int dim = domain->dimension;

    int k_nlocal = atom->nlocal;

    int *k_mask = atom->mask;

    double **x = atom->x;

    int *k_type = atom->type;

    double htemp, ltemp;

    double mdboxdiff[3], overlapdiff[3];

    zone_change = 0;

    for(i=0; iinversemask[ov_srdgroup];

    zone_change = 1;

    }

    if(k_mask[i] & ov_biggroupbit){

    k_mask[i] &= group->inversemask[ov_biggroup];

  • - 47 -

    k_mask[i] |= in_biggroupbit;

    zone_change = 1;

    }

    } else {

    if(k_mask[i] & shadowgroupbit){

    k_mask[i] &= group->inversemask[k_srdgroup];

    k_mask[i] |= k_mdgroupbit;

    k_type[i] = new_type;

    zone_change = 1;

    }

    if(k_mask[i] & k_biggroupbit){

    k_mask[i] &= group->inversemask[in_biggroup];

    zone_change = 1;

    }

    for(k=0; kinversemask[ov_srdgroup];

  • - 48 -

    zone_change = 1;

    }

    if(k_mask[i] & k_biggroupbit){

    k_mask[i] &= group->inversemask[ov_biggroup];

    zone_change = 1;

    }

    }

    }

    }

    if(dim == 2){

    if((overlapdiff[0] < 0) && (overlapdiff[1] < 0)){

    if((k_mask[i] & k_mdgroupbit) && (k_mask[i] & shadowgroupbit)){

    k_mask[i] &= group->inversemask[k_mdgroup];

    k_mask[i] |= k_srdgroupbit;

    k_type[i] = srd_type;

    zone_change = 1;

    }

    if(k_mask[i] & ov_srdgroupbit){

    k_mask[i] &= group->inversemask[ov_srdgroup];

    zone_change = 1;

    }

    if(k_mask[i] & ov_biggroupbit){

    k_mask[i] &= group->inversemask[ov_biggroup];

    k_mask[i] |= in_biggroupbit;

    zone_change = 1;

    }

    } else {

    if(k_mask[i] & shadowgroupbit){

    k_mask[i] &= group->inversemask[k_srdgroup];

    k_mask[i] |= k_mdgroupbit;

    k_type[i] = new_type;

    zone_change = 1;

    }

  • - 49 -

    if(k_mask[i] & k_biggroupbit){

    k_mask[i] &= group->inversemask[in_biggroup];

    zone_change = 1;

    }

    for(k=0; kinversemask[ov_srdgroup];

    zone_change = 1;

    }

    if(k_mask[i] & k_biggroupbit){

    k_mask[i] &= group->inversemask[ov_biggroup];

    zone_change = 1;

    }

    }

    }

    }

    }

    check_reorder();

    make_ovlist();

    }

    /* ---------------------------------------------------------------------- */

  • - 50 -

    void FixSBMD::check_reorder()

    {

    int all_check = 0;

    MPI_Allreduce(&zone_change, &all_check, 1, MPI_INT, MPI_MAX, world);

    if(all_check > 0) {

    atom->first_reorder();

    next_reneighbor = update->ntimestep;

    }

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::make_ovlist()

    {

    int k_nlocal = atom->nlocal;

    int *k_mask = atom->mask;

    int i;

    novbig = 0;

    novsrd = 0;

    if(nmaxlocal < k_nlocal){

    nmaxlocal += DELTA;

    lovbig = memory->grow(lovbig,nmaxlocal,"fix_sbmd:lovbig");

    lovsrd = memory->grow(lovsrd,nmaxlocal,"fix_sbmd:lovsrd");

    }

    for(i=0; i

  • - 51 -

    {

    if (n == 0) nmaxclone += DELTA;

    else nmaxclone = n;

    clone_x = memory->grow(clone_x,nmaxclone,3,"fix_sbmd:clone_x");

    clone_v = memory->grow(clone_v,nmaxclone,3,"fix_sbmd:clone_v");

    clone_f = memory->grow(clone_f,nmaxclone,3,"fix_sbmd:clone_f");

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::backup_ov_srd(int jflag)

    {

    double **x = atom->x;

    double **v = atom->v;

    double **f = atom->f;

    int i,j;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; i

  • - 52 -

    double **x = atom->x;

    double **v = atom->v;

    double **f = atom->f;

    int i,j;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; if;

    int i,j;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; i

  • - 53 -

    };

    if(( jflag == ALL)||( jflag == V))

    for(i=0; iv;

    double **f = atom->f;

    int i,j;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; i

  • - 54 -

    for(i=0; inlocal;

    double **x = atom->x;

    double **v = atom->v;

    double **f = atom->f;

    int i;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; iv;

  • - 55 -

    double **f = atom->f;

    int i;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; iv;

    double **f = atom->f;

    double swap_x[3], swap_v[3], swap_f[3];

    int i;

    if(( jflag == ALL)||( jflag == X))

    for(i=0; i

  • - 56 -

    clone_x[i][0] = swap_x[0];

    clone_x[i][1] = swap_x[1];

    clone_x[i][2] = swap_x[2];

    };

    if(( jflag == ALL)||( jflag == V))

    for(i=0; itype;

    int i,j;

  • - 57 -

    for(i=0; iinversemask[k_mdgroup];

    k_type[ j] = srd_type;

    }

    }

    /* ---------------------------------------------------------------------- */

    void FixSBMD::ov_srd_off()

    {

    int *k_mask = atom->mask;

    int *k_type = atom->type;

    int i,j;

    for(i=0; iinversemask[k_srdgroup];

    k_type[ j] = new_type;

    }

    }

    /* ---------------------------------------------------------------------- */

    double FixSBMD::memory_usage()

    {

    double bytes = 0.0;

    // if (varflag == ATOM) bytes = atom->nmax*3 * sizeof(double);

    return bytes;

    }

  • - 58 -

    Appendix. B. LAMMPS 설치

    본 장에서는 LAMMPS를 설치하는 과정을 설명한다. LAMMPS 패키지는

    LAMMPS 웹사이트를 통해서 구할 수 있다[3]. 병렬 버전의 설치를 위해서는

    MPICH와 같은 병렬 프로그래밍 라이브러리가 선행되어 설치되어 있어야 하며

    퓨리에 변환 라이브러리인 fftw가 필요하다. 설치 과정은 다음과 같다.

    (1) lammps.tar.gz을 LAMMPS 웹사이트에서 다운로드 하고 압축을 해제한다.

    tar -xzvf lammps.tar.gz

    'lammps-3Feb13'와 같은 LAMMPS용 소스파일 디렉토리가 생성된다.

    (2) 소스 디렉토리로 이동하여 필요한 유저 패케지를 설치한다.

    cd lammps-3Feb13/src

    make yes-USER-OMP

    => installing Package USER-OMP

    ☺ LAMMPS는 샌디아 연구소에서 개발된 기본 소프트웨어에 제3자가 개발한

    추가 패케지를 포함하고 있다. 이들은 USER-XXX 형태의 디렉토리를 가지고

    있으며 특정한 유저 패케지를 사용하기 위해서는 LAMMPS 컴파일 전에

    'make yes-USER-XXX'를 통해 해당 패케지의 소스 파일들을 LAMMPS 소스 파

    일들에 포함시켜야 한다. 포함된 특정 유저 패케지 소스 파일들을 제거하기

    위해서는 'make no-USER-XXX'를 수행하면 된다. 설치된 패케지들의 종류를 확

    인하고자 할때는 'make package-status'를 수행한다.

    (3) 소스 디렉토리의 MAKE 디렉토리로 이동하여 Make용 파일을 생성한다.

    cd lammps-3Feb13/src/MAKE

    cp Makefile.g++3 Makefile.kisti

    vi Makefile.kisti

    'Makefile.g++3'와 같은 파일을 복사한 뒤 수정하여 사용하도록 한다. 다음의 파

    일을 참조하여 Make용 파일을 생성하도록 한다.

  • - 59 -

    # g++3 = RedHat Linux box, g++ (v3), MPICH2, FFTW

    SHELL = /bin/sh

    # ---------------------------------------------------------------------

    # compiler/linker settings

    # specify flags and libraries needed for your compiler

    CC = /home01/khocha/mpi/mvapich2org/bin/mpicxx

    CCFLAGS = -g -O

    DEPFLAGS = -M

    LINK = /home01/khocha/mpi/mvapich2org/bin/mpicxx

    LINKFLAGS = -g -O

    LIB =

    ARCHIVE = ar

    ARFLAGS = -rc

    SIZE = size

    # ---------------------------------------------------------------------

    # LAMMPS-specific settings

    # specify settings for LAMMPS features you will use

    # if you change any -D setting, do full re-compile after "make clean"

    # LAMMPS ifdef settings, OPTIONAL

    # see possible settings in doc/Section_start.html#2_2 (step 4)

    LMP_INC = -DLAMMPS_GZIP

    # MPI library, REQUIRED

    # see discussion in doc/Section_start.html#2_2 (step 5)

    # can point to dummy MPI library in src/STUBS as in Makefile.serial

    # INC = path for mpi.h, MPI compiler settings

    # PATH = path for MPI library

    # LIB = name of MPI library

    MPI_INC = -DMPICH_SKIP_MPICXX

  • - 60 -

    MPI_PATH =

    MPI_LIB = -L/home01/khocha/mpi/mvapich2org/lib -lmpich

    # FFT library, OPTIONAL

    # see discussion in doc/Section_start.html#2_2 (step 6)

    # can be left blank to use provided KISS FFT library

    # INC = -DFFT setting, e.g. -DFFT_FFTW, FFT compiler settings

    # PATH = path for FFT library

    # LIB = name of FFT library

    FFT_INC = -I/opt/FFTW2/include -DFFT_FFTW

    FFT_PATH =

    FFT_LIB = -L/opt/FFTW2/lib -lfftw

    # JPEG library, OPTIONAL

    # see discussion in doc/Section_start.html#2_2 (step 7)

    # only needed if -DLAMMPS_JPEG listed with LMP_INC

    # INC = path for jpeglib.h

    # PATH = path for JPEG library

    # LIB = name of JPEG library

    JPG_INC =

    JPG_PATH =

    JPG_LIB =

    # ---------------------------------------------------------------------

    # build rules and dependencies

    # no need to edit this section

    include Makefile.package.settings

    include Makefile.package

    EXTRA_INC = $(LMP_INC) $(PKG_INC) $(MPI_INC) $(FFT_INC) $(JPG_INC)

    $(PKG_SYSI