Określenie każdego aspektu algorytmu jest uciążliwe dla użytkownika. Jeśli algorytm dopuszcza zagnieżdżone komponenty, nie będzie wystarczająca skończona liczba opcji. Dlatego bardzo ważne jest, aby opcje niekoniecznie „zwiększały się” do najwyższego poziomu, jak w przypadku jawnych argumentów lub parametrów szablonu. Jest to czasami nazywane „problemem konfiguracyjnym” w inżynierii oprogramowania. Wierzę, że PETSc ma wyjątkowo wydajny system zarządzania konfiguracją. Jest podobny do wzorca Service Locator w eseju Martina Fowlera na temat odwrócenia kontroli .
System konfiguracji PETSc działa poprzez kombinację konfiguracji określonej przez użytkownika zarządzanej przez obiekty solvera (z zapytaniami get i set) oraz bazą danych opcji. Każdy element symulacji może zadeklarować opcję konfiguracji, wartość domyślną i miejsce do umieszczenia wyniku. Zagnieżdżone obiekty mają prefiksy, które można komponować, dzięki czemu każdy obiekt wymagający konfiguracji można adresować niezależnie. Same opcje można odczytać z wiersza poleceń, środowiska, plików konfiguracyjnych lub z kodu. Po zadeklarowaniu opcji określa się ciąg pomocy i stronę podręcznika, aby -help
opcja była zrozumiała i aby można było napisać poprawnie połączony interfejs GUI.
Użytkownik wywołuje SetFromOptions
metodę, aby obiekt sam się skonfigurował na podstawie opcji wiersza poleceń. Wywołanie tej funkcji jest opcjonalne i może nie zostać wywołane, jeśli użytkownik (osoba pisząca kod wywołujący PETSc) udostępnia opcje za pośrednictwem innego interfejsu. Zdecydowanie zalecamy, aby użytkownik ujawnił bazę danych opcji, ponieważ daje to użytkownikowi końcowemu (osobie uruchamiającej aplikację) dużą moc, ale nie jest to wymagane.
Typowa konfiguracja, nazywana przez
PetscObjectOptionsBegin(object); /* object has prefix and descriptive string */
PetscOptionsReal("-ts_atol", /* options database key */
"Absolute tolerance for local truncation error", /* long description */
"TSSetTolerances", /* function and man page on topic */
ts->atol, /* current/default value *?
&ts->atol, /* place to store value */
&option_set); /* TRUE if the option was set */
PetscOptionsList("-ts_type","Time stepping method","TSSetType",TSList,
defaultType,typeName,sizeof typeName,&option_set);
TSAdaptSetFromOptions(ts->adapt); /* configures adaptive controller method */
/* ... many others */
/* ... the following is only called from implicit implementations */
SNESSetFromOptions(ts->snes); /* configure nonlinear solver. */
PetscOptionsEnd();
Uwagi:
PetscOptionsList()
przedstawia użytkownikowi wybór z listy dynamicznej. Istnieje architektura wtyczek, która może być wykorzystana przez nowe implementacje do zaprezentowania się jako pierwsza klasa dla osób dzwoniących. (Te implementacje można umieszczać we współdzielonych bibliotekach i używać jako najwyższej klasy bez ponownej kompilacji programów).
SNESSetFromOptions()
rekurencyjnie konfiguruje solwery liniowe, warunki wstępne i wszelkie inne składniki, które wymagają konfiguracji.
Po pierwsze, zrobiłbym algorytm ORAZ oprogramowanie tak ogólne, jak to możliwe. Nauczyłem się tego na własnej skórze.
Załóżmy, że zaczynasz od prostego przypadku testowego. Możesz to zrobić szybciej. Ale jeśli ustawisz zbyt szczegółowe oprogramowanie (zbyt mało parametrów) dla tego początkowego przypadku, tracisz coraz więcej czasu na dostosowanie go za każdym razem, gdy dodajesz nowy stopień swobody. To, co teraz robię, to spędzanie na początku więcej czasu, dzięki czemu sprawa jest dość ogólna i zwiększam zmienność parametrów w miarę postępu.
Wymaga to więcej testów od samego początku, ponieważ będziesz mieć więcej parametrów od punktu początkowego, ale oznacza to, że możesz później dużo grać z algorytmem przy zerowym lub bardzo niskim koszcie.
Przykład: algorytm polega na obliczeniu całki powierzchniowej iloczynu kropkowego dwóch funkcji wektorowych. Nie zakładaj od samego początku rozmiaru, geometrii i dyskretyzacji powierzchni, jeśli w przyszłości będziesz chciał to zmienić. Wykonaj funkcję iloczynu, spraw, aby powierzchnia była jak najbardziej ogólna, oblicz całkę w przyjemny formalny sposób. Możesz przetestować każdą wykonaną funkcję osobno.
Na początku możesz i zaczniesz integrować proste geometrie i deklarować parametry may na początku jako stałe. Z biegiem czasu, jeśli chcesz zmienić geometrię, możesz to zrobić z łatwością. Gdyby na początku założyć, musiałbyś za każdym razem zmieniać cały kod.
źródło