• Nenhum resultado encontrado

5.5 Acoplamento da Mate Face ao Simulador

5.5.3 Integra¸c˜ao dos C´odigos

Utilizar um c´odigo feito em C++ em Fortran n˜ao ´e uma tarefa simples. Em pri- meiro lugar, C++ ´e uma linguagem orientada a objetos enquanto Fortran ´e estru- turada. Al´em disso, vetores de qualquer dimens˜ao em Fortran podem ter ´ındices negativos, mas n˜ao possuem a posi¸c˜ao zero, j´a em C++ s´o pode haver posi¸c˜oes posi- tivas come¸cando em zero. Isso causou uma adapta¸c˜ao no acoplamento da Mate Face ao simulador. Qualquer referˆencia das vari´aveis internas no simulador que se associe a alguma c´elula da malha necessitou de uma transforma¸c˜ao das posi¸c˜oes.

O desafio de dispor um c´odigo com classes em C++ para o Fortran utilizar foi solucionado criando-se uma camada intermedi´aria entre o c´odigo simulador e a estru- tura Mate Face. Esta camada intermedi´aria possui fun¸c˜oes que acessam os m´etodos da Mate Face.

Um outro problema enfrentado ´e que toda passagem de parˆametro em Fortran ´e por default por referˆencia, podendo ser controlada internamente na rotina. Quando acoplamos um c´odigo em C++ com o Fortran, todas chamadas de fun¸c˜oes s˜ao por re- ferˆencia, for¸cando uma implementa¸c˜ao inteiramente usando ponteiros em C++. Al´em disso, as duas linguagens organizam matrizes de modo diferente, uma sequenciando em mem´oria linhas seguidas de linhas, e a outra sequenciando as colunas, ou seja,

5.5 Acoplamento da Mate Face ao Simulador 103 uma matriz em Fortran ´e a transposta em C++ quando for feito um alinhamento em mem´oria ou c´opia bit a bit.

A camada intermedi´aria que foi constru´ıda para dispor fun¸c˜oes que acessam os m´etodos da Mate Face foi chamada de Interface. Ela realmente funciona como uma interface entre os dois c´odigos e foi constru´ıda em C++ como um conjunto de fun¸c˜oes em um bloco de exporta¸c˜ao (export). Todas essas fun¸c˜oes da interface possuem seus parˆametros como ponteiros, para serem compat´ıveis para serem chamados pelo c´odigo em Fortran.

Para integrar estes dois c´odigos, utilizou-se os compiladores da GNU, tanto para Fortran (f77) quanto para C++ (g++), pois s˜ao compat´ıveis entre si. Mas para a com- pila¸c˜ao ser realizada com sucesso, todas vers˜oes de codifica¸c˜ao devem ser a mesma em cada linguagem. Isso n˜ao ocorria com o c´odigo do simulador. Uma por¸c˜ao do c´odigo estava feita em Fortran 90 enquanto que sua grande maioria estava codificada em Fortran 77. Ent˜ao, foi feita uma reescrita do c´odigo que estava em Fortran 90 para a vers˜ao 77 de modo a compatibilizar os compiladores. Como o c´odigo do simu- lador e a estrutura de dados foram desenvolvidos utilizando diferentes linguagens de programa¸c˜ao, uma etapa de integra¸c˜ao do simulador (Fortran) e a Mate Face (C++) foi realizada em tempo de compila¸c˜ao. Primeiro compila-se a interface junto com a Mate Face gerando uma biblioteca (arquivo objeto de extens˜ao .o), que possui todos os procedimentos dentro do bloco de exporta¸c˜ao com suas assinaturas convertidas. Em seguida, compilou-se o c´odigo do simulador acrescentando-se a biblioteca gerada no passo anterior na sua lista de lincagem do programa principal.

Portanto, a troca de informa¸c˜oes entre o simulador e a Mate Face ´e realizada por uma interface. A maneira como esta interface atua pode ser vista na Figura 5.6, codificada em C++, composta por um conjunto de procedimentos devidamente configurados para serem acessados por um programa Fortran. A interface traduz e controla todas as chamadas aos m´etodos implementados na estrutura de dados feitas pelo simulador. Toda troca de informa¸c˜ao entre os m´odulos ´e feita em mem´oria

principal e em tempo de execu¸c˜ao de forma autom´atica pela interface. Mate Face Código do Simulador C++ Subrotinas compatíveis com FORTRAN

Estrutura de Dados Topológica

ENO O era o e p d r s de

m h al a

FORTRAN

Biblioteca para acesso à Mate Face Simulador

WENO Dados da Malha

on u ta a C s l s n r ações a m a i fo m d alh r e Reto no d a consultas à malh o su trad zi a C n lta u d Controlador de Movimentação de malhas Biblioteca de Interface ti s Mover vér ce e q ar m h ade u al a

Figura 5.6: Esquema de integra¸c˜ao dos c´odigos Fortran 77 (Brud2D) e C++ (Mate Face).

A interface ´e definida por um conjunto de procedimentos que s˜ao acessados di- retamente do simulador. Todas as chamadas de procedimentos na interface ´e feita diretamente em mem´oria principal, onde uma lista de parˆametros de cada procedi- mento compartilha uma regi˜ao da mem´oria (ponteiro em C++). ´E dessa maneira que o simulador desenvolvido em Fortran tem acesso `as informa¸c˜oes acessadas na inter- face. Esta, por sua vez, transforma toda funcionalidade da estrutura de dados Mate Face em procedimentos. E por compatibilidade, todos procedimentos possuem suas listas de parˆametros definidas como ponteiros aos tipos de dados transmitidos.

Um aspecto computacional muito importante foi a defini¸c˜ao da equivalˆencia dos tipos de dados entre o c´odigo do simulador e a interface que acessa a Mate Face. Al´em do alinhamento de mem´oria ser diferente, como j´a explicado o caso das matrizes serem transpostas, o tipo de dado precisa ser compat´ıvel caso contr´ario a informa¸c˜ao passada ser´a incorreta. Al´em disso, v´arios cuidados devem ser tomados para que o acoplamento seja compat´ıvel.

A primeira regra ´e a equivalˆencia dos tipos de dados. Em Fortran e em C++, os tipos definidos de dados utilizam diferentes bytes na aloca¸c˜ao em mem´oria principal. Ent˜ao, quando um procedimento escrito e compilado em C++ ´e exportado para ser

5.5 Acoplamento da Mate Face ao Simulador 105

C++ Fortran 77

unsigned char byte

short int integer*2

long int e int integer

int matriz[3][2] integer matriz(2,3) long int ou int logical

bool logical*1

float real

double real*8

long double real*16

#define parameter

Tabela 5.1: Equivalˆencia de tipos de dados entre Fortran e C++

utilizado em Fortran, deve haver uma equivalˆencia dos tipos de dados em todos os seus parˆametros. Essa equivalˆencia pode ser visualizada na Tabela 5.1.

Deste modo, foi utilizada a Tabela 5.1 para definir os tipos de dados que a interface e o simulador manipulam em mem´oria, para n˜ao haver perda de informa¸c˜ao.

Os procedimentos criados na interface seguem um padr˜ao para uma compila¸c˜ao espec´ıfica para lincagem posterior. Para serem utilizados no Fortran, os procedi- mentos na interface em C++ devem estar dentro de um escopo de extern “C”. Um requerimento adicional ´e que todos os procedimentos na interface retornem void.

Na interface, os nomes dos procedimentos devem finalizar com um caractere adi- cional “ ” ao final do nome do procedimento na interface. Ao ser chamado no c´odigo Fortran, este procedimento ´e chamado sem este caracter adicional. Por exemplo, considere um procedimento chamado initialize, que inicializa a Mate Face alocando mem´oria para a estrutura. Na interface, o m´etodo estaria declarado como “void initialize (void);”, j´a no programa do simulador em Fortran a chamada seria “call initialize()”, ou seja, sem o caractere final.

Al´em de incluir o caractere extra no final de cada nome de procedimento, todos os parˆametros nos procedimentos na interface devem ser passados como ponteiros, pois todos parˆametros em Fortran s˜ao passados por referˆencia. Por exemplo, para recupe- rar o centroide de uma c´elula, em Fortran chamar´ıamos o m´etodo por “call getcen-

Fortran: REAL*8 X INTEGER A,B,C COMMON/ABC/ X,A,B,C C++: extern “C”{ extern struct { double x; int a,b,c; } abc ; }

Tabela 5.2: Equivalˆencia de blocos de mem´oria entre Fortran e C++

troid(cellid, centx, centy)”, onde cellid ´e o identificador da c´elula e centx, centy, s˜ao as vari´aveis onde estar˜ao armazenadas os valores das coordenadas do centroide daquela c´elula (parˆametro de sa´ıda). A implementa¸c˜ao dessa chamada na interface ´e “void getcentroid(int *cellid, double *centx, double *centy);”, ou seja todos os parˆametros s˜ao ponteiros para as ´areas de mem´oria compartilhada ao programa Fortran. Deste modo, os procedimentos na interface v˜ao decidir quais parˆametros s˜ao de entrada, e quais s˜ao os de sa´ıda.

A passagem de strings (cole¸c˜ao de caracteres) s˜ao diferentes entre os dois compi- ladores. Uma chamada do tipo “call setfile(string a, string b)” em Fortran deve ser tratada em C++ por “setfile(char *string a, leng a, char *string b, leng b);”, ou seja, o tamanho das strings deve ser passado ap´os cada string no parˆametro do procedi- mento.

Apesar de n˜ao ser poss´ıvel referenciar objetos instanciados de classes em C++ em Fortran, ´e poss´ıvel compartilhar blocos de dados em mem´oria, quando necess´ario. As structs em C++ s˜ao equivalentes aos common blocks em Fortran. Mas para isso deve- se definir o bloco em C++ com o mesmo nome do definido em Fortran, adicionar o caractere ao final dele e externaliz´a-lo. Por exemplo, a Tabela 5.2 mostra um exemplo de common block em Fortran, e sua equivalˆencia em C++.

5.5 Acoplamento da Mate Face ao Simulador 107