2012-05-25 11 views
5

Estoy diseñando un código Fortran para resolver un sistema PDE.Un buen diseño OOP para un solucionador con Fortran moderno

La forma en que está diseñado ahora es que tengo un tipo Variable que tiene varios atributos, el más importante de los cuales es la matriz val que almacena el valor.

Ahora también tengo una clase solver, que realizaría cálculos en un variable. Pensé que pasar el variable completo al solucionador y trabajar con variable%val cada vez que quisiera ejecutarlo (varios miles de veces durante una ejecución) sería ineficiente, así que decidí definir campos de puntero en la clase solver para enlazar el solucionador a la variable apropiada. Por ejemplo

program example 
    use variable 
    use solvers 

    type(Variable) T 
    type(Solver) solver_temperature 

    !Contructors 
    call T%create() 
    call solver_temperature%create(T) 

    call solver_temperature%solve() 
end program example 

y el módulo solucionador

module solvers 
type Solver 
    real*8, pointer :: T(:,:) 

contains 
    procedure :: create 
    procedure :: solve 
end type 

contains 
    subroutine create(this,T) 
     type(Solver) :: this 
     type(Variable) :: T 

     this%T => T%val 
    end subroutine 
end module 

En mi programa defino diferentes variables para diferentes propiedades físicas y diferentes solucionadores que están asociados con esas variables en la forma en que he mostrado antes.

Soy nuevo en OOP en general, entonces mi pregunta es si ese es un diseño decente. Especialmente desde el punto de vista del rendimiento. ¿Cómo se compara esto con hacer T solo una matriz y pasarla a una subrutina solve en términos de velocidad? ¿Hay alguna forma regular de hacer esto?

+2

No veo mucho sentido en el puntero de la variable. Simplemente pasarlo como un argumento falso me parece más natural. Es solo un descriptor de matriz, nada malo para el rendimiento. –

Respuesta

5

He estado trabajando con las características OO de Fortran durante un año más o menos, aquí hay algunos comentarios extendidos enmascarados como una respuesta.

Si simplemente le preocupa la velocidad de ejecución en bruto, probablemente sea, en general (y se base en argumentos y mi experiencia en lugar de datos), mejor evitar las características de OO; pero en muchos casos se puede hacer el mismo argumento de que es mejor mantenerse al margen de cualquier cosa que se agregue al idioma después de FORTRAN77.

Los argumentos a favor de OO son más fuertes cuando se basan en cuestiones de diseño de código, comprensibilidad, extensibilidad, ese tipo de cosas. Si esto te importa, entonces deberías pensar en usar las características de OO.

Como Vladimir ya ha comentado, no parece tener mucho sentido usar el puntero variable. No olvide que la mayoría de las implementaciones de Fortran hacen llamadas por referencia específicamente para evitar el esfuerzo de copiar (grandes volúmenes de) datos.

Personalmente, no me gusta la forma en que ha definido su procedimiento de escritura de tipo create. Me gusta mucho más para poner en práctica ese tipo de operación en función, por lo que puedo escribir frases como esta:

t = solver%new() 

en lugar de su

call T%create() 

Nota esto es una preferencia mía, y es más una cuestión de estilo que de eficiencia o corrección. Noté que no ha declarado los intentos de los argumentos a la subrutina create; tal vez porque solo ha publicado un fragmento de su código.

Debido a que OO es relativamente nuevo en Fortran (y, posiblemente, relativamente desconocido para la mayoría de las personas que trabajan en los dominios donde se usa Fortran ampliamente) no hay mucho material útil para guiarnos en su adopción.Yo recomendaría Scientific Software Design. Proporciona al tema una cobertura decente y plantea el argumento de por qué los programadores científicos y de ingeniería deberían adoptar OO.

+0

+1 También me gusta la inicialización como una función, ya que otros enfoques con los constructores (aunque la asignación de memoria se realiza en otro lugar). A veces es incluso útil crear una interfaz para la solución% new con el nombre solucionador y luego usar 't = solver()' incluso en casos donde la inicialización de tipo derivada estándar no es suficiente. –

+0

Tanques mucho para el enlace del libro, intentaré conseguir eso. – tiam

+0

en su ejemplo 'solver% new()', ¿qué es 'solver'? Un objeto Solver? ¿O puede acceder a las funciones de tipo de esta manera? – weymouth

Cuestiones relacionadas