epicf / ef_python

Low-energy charged particles' dynamics simulation using particle-in-cell method (Ef, python version)
MIT License
8 stars 11 forks source link

Visualize coordinate mesh and boundary conditions, particle sources and inner regions #11

Closed fizmat closed 6 years ago

noooway commented 6 years ago

Привет!

Посмотрел код. Все, конечно, сделано гораздо круче, чем обычно пишу я. Здорово, что работают примеры и визуализация всех полей конфига. Даже потенциалы. Процедура расчетов наконец-то сильно упростится!

Я пока не разобрался в деталях, как все реализовано. Но хотел бы составить себе хотя бы высокоуровневое впечатление. Думаю, что в течение нескольких дней, в крайнем случае недели, я это сделаю.

Я попробую сформулировать здесь свое понимание и какие-то вопросы (если будут). Потом можно будет залить код в master-ветку.

Хотя можно, конечно, уже и сейчас залить...

fizmat commented 6 years ago

Я люблю повторяться поменьше и питон позволяет сильно всё сокращать, но есть опасность, что я из-за этого заворачиваю нечитаемые конструкции. Главная цель переделки конфига в виде двух "слоёв" классов - оставить совместимый с проектом ef набор классов - секций конфига, но при этом иметь возможность менять структуру внутреннего представления конфига на более удобную, которую можно например и рисовать.

noooway commented 6 years ago

В-общем, я начал смотреть код, но не успел за "несколько дней или в крайнем случае неделю", как обещался. Потом выпал примерно на месяц из деятельности по этой программе. Нехорошо получилось.

Думаю, чтобы такого больше не повторялось - чтобы готовая функциональность не висела месяц без дела - наверное, будет лучше вносить изменения без моего подтверждения. А потом я уже буду разбираться, что и как работает.

Ладно. Как я понял, ситуация следующая:

Есть два параллельных набора классов: одни наследуются от ConfigComponent, вторые - от ConfigSection. Например, class TimeGrid(ConfigComponent) и class TimeGridConf(ConfigSection).

"Компоненты" (те, что наследуются от ConfigComponent) что-то знают про свое содержимое. В частности, умеют его визуализировать. Данные хранятся в удобном для этого формате.

Собственно, единственный метод в ConfigComponent это visualize. Предполагается, что в наследуемых классах он будет переопределяться по мере надобности.

    class ConfigComponent(DataClass):
        def visualize(self, visualizer):
            pass

"Секции" (те, что наследуются от ConfigSection) нужны для конвертации данных между форматом конфига расчетной программы и форматом в компонентах. Они общаются в-основном с питоновским Config Parser'ом: импорт с помощью конструктора from_section(cls, section) и экспорт с помощью add_section_to_parser(self, conf).

Для секций с именами (типа ParticleSourceBox.cathode) есть NamedConfigSection.

Декоратор @register добавляет соответствие между названием секции в конфиге расчетной программы и классом, унаследованным от ConfigSection. Добавляет в словать section_map в классе ConfigSection. Поскольку этот класс родительский для всех секций, section_map оказывается общей для всех классов-потомков. Кстатии, почему register определен два раза? Один раз как classmethod в ConfigSection и один раз глобально?

В каждом Section-классе определен метод make, который позволяет собрать объект класса Component из этого Section-объекта.

Каждый section-класс, который можно отобразить в component-класс, определяется в фаиле component-класса. Например, @register \n class InnerRegionBoxConf(NamedConfigSection) определен в components/inner_region.py вместе с компонентом InnerRegion(ConfigComponent). Поля конфига расчетной программы вписываюстя в ContentTuple как именованный кортеж. Данными из ContentTuple инициализируется self.content, который потом используется для экспорта в конфиг расчетной программы в add_section_to_parser.

Т.е. в итоге если мне нужно добавить новую секцию в конфиг расчетной программы, то мне нужно 1) определить component-класс, который будет его визуализировать. 2) зарегистрировать section-класс, который будет отвечать за конвертацию между component-классом и конфигом расчетной программы. За импорт из конфига программы в component отвечает метод make section-класса, за экспорт из component-класса в section отвечает метод to_conf component-класса.

Классы ConfigComponent, ConfigSection и EfConf наследуются от DataClass, чтобы не переопределять каждый раз встроенные методы: __repr__ , __hash__ и __eq__. Где-нибудь в коде эти методы явно используются? Или это просто правила приличия?

Еще геометрические формы источников и внутренних областей обобщены (и унаследованы от Shape()). Есть визуализатор этих объектов, в написание которого тоже было вложено много усилий. Умеет как wireframe, так и solid. Знает про потенциалы. Использует только matplotlib. Есть наклон для оси цилиндра. В-общем, очень круто.