From eef9f59a56b010af5aa82a8a65378f27f58e3af8 Mon Sep 17 00:00:00 2001 From: ignis Date: Thu, 4 Jun 2026 01:57:27 +0000 Subject: [PATCH] refactor: enforce ISP and LSP compliance (Phase 2) --- code/code_gen/post.py | 124 ++++++++++++++++++++---------------------- 1 file changed, 59 insertions(+), 65 deletions(-) diff --git a/code/code_gen/post.py b/code/code_gen/post.py index 8a9a267..341f94e 100644 --- a/code/code_gen/post.py +++ b/code/code_gen/post.py @@ -765,69 +765,75 @@ def make_allocate(name, shape, init_zero=True): return alloc_str -class FieldBase (object): - """모든 물리 필드 객체의 최상위 기본 클래스로서 공통 데이터 구조 및 선언/할당 문자열 작성을 담당합니다.""" - def __init__ (self, name, fdict): +class DependencyNode(object): + """의존성 관계 분석을 담당하는 추상 인터페이스 및 노드 클래스입니다.""" + def __init__(self, name, fdict): self.name = name - self.array = name # 실제 메모리 버퍼 상의 지칭 배열 명칭 + self.fdict = fdict self.dep = set([]) # 종속된(의존 중인) 하위 필드 리스트 self.fluc = False # 변동량 편차 계산 대상인지 여부 + + def depends_on(self, a): + return a in self.dep + + def is_fluctuation(self): + return self.fluc + + def checkFluctuation(self): + """본 변수 혹은 의존하고 있는 하위 기호들 중에 변동량(Fluctuation) 관련 계산이 개입되어 있는지 + 상향식으로 전파 추적하는 재귀 메서드입니다. + """ + fset = set([]) + for d in map(self.fdict.get, self.dep): + fset.update(d.checkFluctuation()) + if self.is_fluctuation() or len(fset) > 0: + fset.add(self.name) + return fset + + def depClosure(self): + """해당 변수를 계산하기 위해 선행 계산되어야 하는 모든 하위 변수 노드들을 + 재귀적으로 타고 내려가 총합 폐쇄 집합(Closure Set)으로 묶어 반환합니다. + """ + fset = set(self.dep) + for d in self.dep: + fset.update(self.fdict[d].depClosure()) + return fset + + +class Generatable(object): + """Fortran 소스코드 생성이 가능한 필드에 대한 인터페이스입니다.""" + def code(self, alloc=None): + raise NotImplementedError + + def code_decl(self): + real_array_decl = "real(real64), allocatable, dimension({1}) :: {0}" + return real_array_decl.format(self.name, self.dim) + + def code_alloc(self): + return make_allocate(self.name, self.shape) + + def code_free(self): + real_array_free = "deallocate({})" + return real_array_free.format(self.name) + + +class FieldBase (DependencyNode): + """모든 물리 필드 객체의 최상위 기본 클래스로서 공통 데이터 구조를 정의합니다.""" + def __init__ (self, name, fdict): + super(FieldBase, self).__init__(name, fdict) + self.array = name # 실제 메모리 버퍼 상의 지칭 배열 명칭 self.prime = False # 기본 데이터 파일로부터 읽어 들이는 원본 필드인지 여부 - self.fdict = fdict self.shape = "nxp,nyp,nzp" # 3차원 그리드 구조 self.dim = ":,:,:" - def depends_on (self, a): - return (a in self.dep) - - def is_fluctuation (self): - return self.fluc - def export_on (self): return False def __repr__ (self): return self.name - def checkFluctuation (self): - """본 변수 혹은 의존하고 있는 하위 기호들 중에 변동량(Fluctuation) 관련 계산이 개입되어 있는지 - 상향식으로 전파 추적하는 재귀 메서드입니다. - """ - fset = set([]) - for d in map(self.fdict.get, self.dep): - fset.update(d.checkFluctuation()) - - if self.is_fluctuation() or len(fset) > 0: - fset.add(self.name) - - return fset - - def depClosure (self): - """해당 변수를 계산하기 위해 선행 계산되어야 하는 모든 하위 변수 노드들을 - 재귀적으로 타고 내려가 총합 폐쇄 집합(Closure Set)으로 묶어 반환합니다. - """ - fset = set(self.dep) - - for d in self.dep: - fset.update(self.fdict[d].depClosure()) - - return fset - - - def code_decl (self): - real_array_decl = "real(real64), allocatable, dimension({1}) :: {0}" - return real_array_decl.format(self.name, self.dim) - - def code_alloc (self): - return make_allocate(self.name, self.shape) - - def code_free (self): - real_array_free = "deallocate({})" - return real_array_free.format(self.name) - - -class FieldExporter (object): +class FieldExporter (Generatable): """물리 필드 데이터를 병렬 분산 디스크 시스템으로 직접 추출(Export)하는 고성능 MPI-IO 서브루틴 블록을 생성하는 템플릿 처리 클래스입니다. @@ -1001,7 +1007,7 @@ end do -class Field (FieldBase): +class Field (FieldBase, Generatable): """일반 대입 계산 변수를 관리하며, 3차원 격자점 루프 코드 생성을 담당하는 핵심 클래스입니다. SymPy 최적화 및 CSE 적용 코드를 루프 본문에 결합합니다. """ @@ -1077,7 +1083,7 @@ end block return calculation_code + export_code -class FluctuationField (FieldBase): +class FluctuationField (FieldBase, Generatable): """물리 필드의 난류 변동 성분(Fluctuation, u' = u - )을 계산하기 위한 변수 클래스입니다. 수식 내의 u' 기호를 평균량과의 차이 수식으로 팽창하여 할당합니다. """ @@ -1149,20 +1155,8 @@ class PrimaryField (FieldBase): self.latex = name self.latex_given = None - def code (self, alloc=None): - return "! {} is read from file".format(self.name) - def code_decl (self): - return "! {} is read from file".format(self.name) - - def code_alloc (self): - return "! {} is read from file".format(self.name) - - def code_free (self): - return "! {} is read from file".format(self.name) - - -class DerivedField (FieldBase): +class DerivedField (FieldBase, Generatable): """수치 공간 미분(ddx, d2dy 등)을 수행하여 계산되는 유도 필드 클래스입니다. Fortran 수치 차분 패키지 서브루틴(Compact.f90 에 구현된 dfnonp, dfp 등)의 동적 호출 코드를 출력합니다. @@ -1185,7 +1179,7 @@ class DerivedField (FieldBase): return "call {0} ( {2}, {1} )".format(self.op, varray, self.array) -class AveragedField (FieldBase): +class AveragedField (FieldBase, Generatable): """특정 물리 필드를 격자의 동질 차원(예: X 방향 1D선상 평균)에 대해 공간 통계 평균(Average) 연산을 수행하는 1차원 필드 클래스입니다. """