Usando o Data Explorer para Visualizar Dados Gerados pelo ANSYS

Érico Correia da Silva



1 - Abstract

O software ANSYS é um programa para solução de problemas de engenharia pelo método dos elementos finitos. Ele possui diversos recursos de geração de malha e definição de modelo na sua parte de preprocessamento. Na parte de solução, o ANSYS provê recursos para diversos tipos de análises. A parte de posprocessamento do ANSYS também é muito boa mas não chega a ter a riquesa de detalhes que pode-se conseguir com uma visualização feita com o Data Explorer. Desse fato surgiu a ideia de criar um programa capaz de montar um arquivo ".dx" usando dados gerados com o ANSYS. Uma primeira versão desse software já foi feita, chama-se ANSYS2DX. Com essa primeira versão pode-se criar um arquivo ".dx" para visualização das tensões, deformações e deslocamentos, partindo-se de modelos feitos com o ANSYS, compostos por elementos planos de quatro nós, ou por elementos espaciais de oito nós. O ANSYS2DX foi desenvolvido em C++, possui interface gráfica e pode ser facilmente aprimorado.

Juntamente com o ANSYS2DX foram desenvolvidas dois "visual programs" do DX para manipular esses dados, cada um com uma animação incorporada. A primeira delas faz cortes sucessivos no modelo, mostrando o dado em estudo na superfície e no interior do modelo. A segunda mostra o modelo passando da forma inicial para a forma deformada. Qualquer pessoa com minimos conhecimentos de DX pode usar esses "visual programs" para visualizar um modelo calculado com o ANSYS de diversas formas, apenas usando o "Control Panel" e seus "Interactors" para customizar a visualização.


2 - Introdução e Motivação

Data Explorer é um software de computação gráfica utilizado entre outras coisas para visualização científica. Graças ao seu formato de arquivo de entrada de dados muito flexível, o Data Explorer (ou DX) pode ser usado para análise de problemas físicos dos mais diversos tipos, proporcionando ao pesquisador um estudo visual dos resultados obtidos de ótima qualidade. Dados dificilmente estudados sem recursos de visualização podem ser explorados ao máximo usando-se as inumeras associações possiveis de serem feitas com as diversas ferramentas presentes no DX. Usando o Data Explorer, o pesquisador pode visualizar seus dados usando recursos de animação, enriquecendo ainda mais a análise.

Diferente de outros softwares científicos, o DX não faz cálculos de problemas físicos, ele é um software essencialmente de visualização. Porém, é preciso salientar que o Data Explorer pode ser integrado a outros softwares de cálculo, como é o caso do ANSYS.

ANSYS é um programa usado para tratar problemas de engenharia usando o método dos elementos finitos. Com o ANSYS pode-se fazer naálises de modelos desde os mais simples aos mais complexos, com extrema flexibilidade e com uma vantagem incontextável: "o ANSYS é um software já consagrado e amplamente aprovado pelacomunidade científica e pela indústria em geral".

A parte de pré-processamento do ANSYS possui diversos recursos de geração de malhas, possibilitando uma melhor elaboração de modelos de elementos finitos. O ANSYS possui diversos tipos de elementos que podem ser usados de acordo com o problema em estudo, seja ele um caso em duas dimensões ou um problema tridimensional. O ANSYS pode ser usado em problemas estáticos ou dinâmicos, em problemas de análise de fluidos, em problemas de transferência de calor e em diversos outros problemas físicos onde o método dos elementos finitos é aplicável.

Tal como o pré-processamento e a parte de cálculo, o módulo de pós-processamento do ANSYS apresenta diversos recursos possibilitando uma análise visual completa do problema estudado. Contudo, análises mais aprimoradas podem ser feitas usando um software de visualização, e é desse fato que surgiu a motivação para esse trabalho que tem por objetivo estudar a possibilidade de usar o software Data Explorer para visualizar dados gerados pelo ANSYS, garantindo assim uma analise melhor dos resultados graças a extrema riqueza de detalhes que pode-se conseguir com um programa visual do DX.


3 - Implementação

Todos os trabalhos foram divididos em duas partes:

Com essas duas partes prontas, o usuário do ANSYS pode converter facilmente seus resultados e visualiza-los com mínimos conhecimentos de DX, graças aos programas visuais de exemplo.


4 - Programa de Conversão

Para simplificar os trabalhos optou-se por criar os arquivos do DX partindo-se dos relatórios gerados pelo ANSYS. Dessa forma o conversor deve ler os relatórios do ANSYS, previamente gravados em arquivo texto, gerando arquivos compreensiveis pelo DX. Tal conversor foi batizado de ANSYS2DX e foi implementado em C++ usando a biblioteca wxWindows para garantir uma interface gráfica. Essa primeira versão do ANSYS2DX gera arquivos com tensões, deformações e deslocamentos, partindo de modelos do ANSYS compostos por elementos planos de 3 e 4 nós e espaciais de 8 nós.



Figura 1- ANSYS2DX - Interface gráfica para facilitar


Em modelos ANSYS, um nó pode não estar associado a um elemento, o que implica num cuidado especial no momento da geração do arquivo ".dx", que deve ter cordenadas apenas de nós associados a um dado e a um elemento. Optou-se, então, por carregar todos os nós em memória e gravar apenas os que efetivamente tiverem um dado e um elemento associados. Para isso usou-se a seguinte classe Node:

class Node : public wxObject
{
public:
	Node(long id, long nid, float x, float y, float z) : wxObject() 
	{
		fid = id;	//ANSYS's ID
		fnid = nid;	//DX's ID
		fx = x;
		fy = y;
		fz = z;
		used = 0;	
	}
	int used;
	float fx, fy, fz;
	long fid;
	long fnid;
};

Esta classe é derivada de wxObject apenas para que um objeto dessa classe possa ser armazenado numa lista implementada pela biblioteca wxWindows.

Os passos envolvidos na conversão de modelos ANSYS foram então separados nas seguintes etapas:

Leitura dos relatórios do ANSYS:

O arquivo contendo o relatório do ANSYS é aberto para leitura. São ignoradas todas as linhas até encontrar-se a linha de cabeçário do relatório, pois sabe-se que a linha seguinte ao cabeçário já é referente a um nó, elemento ou dado. Caso a linha do cabeçário não seja encontrada (um arquivo inconsistente), o arquivo não é gerado e o modelo não poderá ser visualizado no DX. Uma vez que a primeira linha de cabeçário foi encontrada, são lidas todas as linhas subsequentes e uma linha com o dado é gravada em um arquivo texto ".out", exceto no caso do relatório de nós que um objeto da classe node é criado e armazenado em memória com os dados para só após a leitura dos elementos ser gerado o arquivo de nós. Se a leitura de uma linha falhar (uma linha diferente das linhas com dados de nós) é feita uma busca pela próxima linha com dados consistentes. Esse procedimento é feito para que as linhas entre uma página e outra do relatório sejam ignoradas. Para exemplificar veja o código abaixo:

	while(!ifile.eof())
	{
		int nn;
		double ex, ey, ez, exy, eyz, exz;
		do
		{
			ifile.getline(stuff, 255, '\n');
		}while(strncmp(stuff, hdr, strlen(hdr)) && !ifile.eof());
		
		if(ifile.eof()) break;
		
		while(!ifile.eof() && !ifile.fail())
		{
		streampos loc = ifile.tellg();
		ifile >> nn >> ex >> ey >> ez >> exy >> eyz >> exz;
		if(ifile.fail())
		{
			ifile.seekg(loc);
			ifile.clear();
			break;
		}
		te++;
		ofile << ex <<" "<< ey <<" "<< ez <<" "<< exy <<" "<< eyz <<" "<< exz << endl;	
		}
	}

No caso da função de conversão de elementos deve-se tomar um cuidado especial, pois programas de elementos finitos em geral listam a conectividade seguindo o sentido anti-horário. Além de gravar os elementos a função CnvElem() marca cada nó que foi encontrado num elemento, para que depois só estes possam ser gravados em WriteNodes().

		while(!ifile.eof() && !ifile.fail())
		{
		streampos loc = ifile.tellg();
		ifile >> ne >> mat >> tp >> r >> e;
		if(ifile.fail())
		{
			ifile.seekg(loc);
			ifile.clear();
			break;
		}
		te++;
		for(int s = 0; s < nn; s++)
		{
			int tn;
			ifile >> tn;
			Node *node = (Node *)(Nodes.Find(tn))->Data();
			if(node)
			{
				n[s] = node->fnid;
				for(wxNode *unode = uNodes.First(); unode; unode = unode->Next())
				{
					Node *cn = ((Node *)unode->Data());
					if(node->fnid > cn->fnid)
						n[s]--;
					
				}
				node->used = 1;
			}
			else
			{
				cout << "referencia a um no inexistente";
				exit(1);
			}
		}
		int tmp = n[1];
		n[1] = n[0]; n[0] = tmp;
		if(nn==8)
		{
		tmp = n[5];
		n[5] = n[4]; n[4] = tmp;
		}
		
		for(int s = 0; s < nn; s++)
		{
			ofile << n[s] <<" ";
		}
		ofile << endl;	
		}

Gravação do arquivo do DX:

Cada uma das funções que trabalham com os relatórios do ANSYS retornam os valores necessários para a geração do arquivo ".dx". Valores como número de nós, número de elementos, etc. Veja abaixo o código que gera o arquivo do DX:

	long nn = CnvNodes();
	long ne = CnvElems();
	long nnw = WriteNodes();
	long nd = CnvData(nn);
	long nscomp = CnvSComp(nn);
	long necomp = CnvEComp();
	long nvu = CnvVecU();

	if(nn > nnw)
	{
		ne = CnvElems();	
	}
	else if(nn < nnw)
	{
		cout << "erro : numero de nos < numero de nos gravados";
		exit(1);
	}
        filebuf  ofb;

	char *fn = dxf->GetValue();
	ofb.open(fn, ios::out);

	ostream ofile(&ofb);

	ofile << "object 1 class array type float rank 1 shape 3 items " 
		<< nnw << " data file " << fnname <<", 0"<< endl;
	ofile << "attribute \"dep\" string \"positions\"" << endl;
	ofile << "#" << endl;
	ofile << "object 2 class array type int rank 1 shape "<< ((rb->GetSelection())? 8 : 4) <<" items " 
		<< ne << " data file " << felname <<", 0"<< endl;
	ofile << "attribute \"element type\" string " << ((rb->GetSelection())? "\"cubes\"" : "\"quads\"") << endl;
	ofile << "attribute \"ref\" string \"positions\"" << endl;
	ofile << "#" << endl;
	if(nd)
	{
	    ofile << "object 3 class array type float rank 1 shape 5 items "
		    << nd << " data file " << fdname <<", 0"<< endl;
	    ofile << "attribute \"dep\" string \"positions\"" << endl;
	    ofile << "#" << endl;
	    ofile << "object \"sprin\" class field" << endl;
	    ofile << "component \"data\" value 3" << endl;
	    ofile << "component \"positions\" value 1" << endl;
	    ofile << "component \"connections\" value 2" << endl;
	    ofile << "attribute \"name\" string \"sprin\"" << endl;
	    ofile << "#" << endl;
	}
	if(nscomp)
	{
	    ofile << "object 4 class array type float rank 1 shape 6 items "
		    << nscomp << " data file " << fscname <<", 0"<< endl;
	    ofile << "attribute \"dep\" string \"positions\"" << endl;
	    ofile << "#" << endl;
	    ofile << "object \"scomp\" class field" << endl;
	    ofile << "component \"data\" value 4" << endl;
	    ofile << "component \"positions\" value 1" << endl;
	    ofile << "component \"connections\" value 2" << endl;
	    ofile << "attribute \"name\" string \"scomp\"" << endl;
	    ofile << "#" << endl;
	}
	if(necomp)
	{
	    ofile << "object 5 class array type float rank 1 shape 6 items "
		    << necomp << " data file " << fecname <<", 0"<< endl;
	    ofile << "attribute \"dep\" string \"positions\"" << endl;
	    ofile << "#" << endl;
	    ofile << "object \"ecomp\" class field" << endl;
	    ofile << "component \"data\" value 5" << endl;
	    ofile << "component \"positions\" value 1" << endl;
	    ofile << "component \"connections\" value 2" << endl;
	    ofile << "attribute \"name\" string \"ecomp\"" << endl;
	    ofile << "#" << endl;
	}
	if(nvu)
	{
	    ofile << "object 6 class array type float rank 1 shape 3 items "
		    << nvu << " data file " << fvuname <<", 0"<< endl;
	    ofile << "attribute \"dep\" string \"positions\"" << endl;
	    ofile << "#" << endl;
	    ofile << "object \"vecu\" class field" << endl;
	    ofile << "component \"data\" value 6" << endl;
	    ofile << "component \"positions\" value 1" << endl;
	    ofile << "component \"connections\" value 2" << endl;
	    ofile << "attribute \"name\" string \"vecu\"" << endl;
	    ofile << "#" << endl;
	}
	ofile << "end" << endl;

O código acima gera um arquivo ".dx" como o que se segue:

object 1 class array type float rank 1 shape 3 items 5520 data file MANCN.out, 0
attribute "dep" string "positions"
#
object 2 class array type int rank 1 shape 8 items 3440 data file MANCE.out, 0
attribute "element type" string "cubes"
attribute "ref" string "positions"
#
object 3 class array type float rank 1 shape 5 items 5520 data file MANCSPRIN.out, 0
attribute "dep" string "positions"
#
object "sprin" class field
component "data" value 3
component "positions" value 1
component "connections" value 2
attribute "name" string "sprin"
#
object 4 class array type float rank 1 shape 6 items 5520 data file MANCSCOMP.out, 0
attribute "dep" string "positions"
#
object "scomp" class field
component "data" value 4
component "positions" value 1
component "connections" value 2
attribute "name" string "scomp"
#
object 5 class array type float rank 1 shape 6 items 5520 data file MANCECOMP.out, 0
attribute "dep" string "positions"
#
object "ecomp" class field
component "data" value 5
component "positions" value 1
component "connections" value 2
attribute "name" string "ecomp"
#
object 6 class array type float rank 1 shape 3 items 5520 data file MANCALLU.out, 0
attribute "dep" string "positions"
#
object "vecu" class field
component "data" value 6
component "positions" value 1
component "connections" value 2
attribute "name" string "vecu"
#
end

O arquivo ".dx" gerado tem a seguinte estrutura:

Cada field tem como componente "data" um array com rank 1, ou seja, os dados de cada field possuem várias colunas. Cada coluna pode ser selecionada e analisada usando a função "select(x,n)" do modulo Compute.


5 - DX Visual Programs

Para o usuário sem experiência com o DX, foram desenvolvidos duas visualizações para trabalhar facilmente com os dados gerados de um modelo do ANSYS. Osusuários que já conecem bem o DX podem usar essas visualizações como ponto de partida, facilitando dessa forma o desenvolvimento de programas visuais mais aprimorados.

A primeira dessas visualizações é bem interativa, possui um Control Panel (figura 2) onde estão diversos Interactors do DX os quais possibilitam um bom nível de interação usuário-visualização, isto é, o pesquisador pode selecionar qual o campoque deseja visualizar e qual tipo de detalhe quer ver. Esse primeiro programa visual faz cortes sucessivos no modelo em estudo e, através do Control Panel, pode-se selecionar o eixo ao longo do qual os cortes serão feitos.



Figura 2-Control Panel da primeira visualização


A segunda visualização já não é tão interativa quanto a primeira para que o usuário possa se acostumar com o Visual Program Editor do DX. Essa visualização implementa uma animação que mostra o modelo passando da forma inicial para a forma deformada.

Ambas as visualizações servem como exemplo para o usuário do DX que pode analisá-las facilmente, pois as duas estão divididas em diversos Execution Groups. São eles:

Um recurso muito utilizado em boa parte das partes citadas acima é a seguinte associação de ferramentas:



Figura 3- Associação de ferramentas


Antes de chegar ao Transmiter do final do Execution Group, os dados passam por um Route que está ligado a um Selector do tipo on-off. Desse Route uma das duas saidas é ligada ao Transmiter e associada a posição on do Selector, a outra nao está ligada a nada. Dessa forma o usuário vai visualizar apenas o que estiver com o Selector na posição on. Isso garante que um usuário sem grandes conhecimentos de Data Explorer possa interagir com a visualização apenas lidando com o Control Panel.

A seguir serão detalhadas apenas as partes de leitura de dados, cálculo de dimensões e plano de corte. As demais partes são associações simples de ferramentas como ClipPlane, AutoColor, ShowBoundary, etc.


5.1 - Leitura dos Dados

Na parte de leitura de dados, o arquivo de entrada pode ser selecionado através de um FileSelector que está ligado a dois Imports, um para ler os campos escalares que serão visualizados com AutoColor, e outro para ler os deslocamentos que é um campo vetorial e, portanto, será vsualizado com o AutoGlyph.



Figura 4- Leitura dos dados


Existe um Selector que está ligado a dois Switchs, um deles ligado ao Import, indicará qual é o field a ser lido do arquivo. O segundo switch por sua vez, possui uma lista com os dados que podem ser selecionado de cada field, ou seja, se o usuário selecionar "tensoes", o primeiro Swhitch resultará em "scomp" (nome do field no arquivo ".dx") e osegundo Switch resultará na seguinte string list:

	{"Sx" "Sy" "Sz" "Sxy" "Syz" "Sxz"}

Essa string list será o stringdata de um outro seletor, que por sua vez indicará qual item do field selecionado deve ser visualizado. Um Compute ligado a esse último Selector e ao Import que trata dos campos escalares, fica encarregado de extrair do field o dado que deseja-se visualizar com a seguinte fórmula:

	select(a,b)

onde:
a = saida do Import
b = saida numérica do ultimo selector


5.2 - Cálculo das Dimensões

Após o usuário ter selecionado o dado a ser visualizado com a sequencia de Selectors, Swhitch e Imports descrita acima, calcula-se o comprimento do modelo para que se torne possível a montagem da animação com a sequência de cortes. Marca-se a parte "positions" do field a ser visualizado e com o auxílio das ferramentas Compute e Statistics o comprimento é calculado subtraindo-se a mínima coordenada da máxima coordenada do eixo ao longo do qual serão feito os cortes.



Figura 5- Calculo das Dimensões



5.3 - Plano de Corte

Esse Execution Group tem por finalidade o calculo de um ponto pertencente ao plano onde será efetuado o corte e de um vetor normal ao plano de corte. Para isso são utilizadas as seguintes fórmulas:

	[(c==0)?b+(a*d):0,(c==1)?b+(a*d):0,(c==2)?b+(a*d):0]

onde:
a = 1/20 do Comprimento do modelo
b = Coordenada minima
c = Eixo para efetuar os cortes (0 = x, 1 = y, 2 = z)
d = Sequencia (resultado do Sequencer, de 0 a 20)

	[(a==0)?1:0,(a==1)?1:0,(a==2)?1:0]

onde:
a = Eixo para efetuar os corte



Figura 6- Plano de Corte



5.4 - Animação para Visualizar os Deslocamentos

O programa visual que implementa uma animação que mostra o modelo saindo da posição inicial até a posição deslocada é basicamente o muito semelhante ao programa que faz cortes sucessivos no modelo. A maior diferença é a ausência da maioria dos recursos de interface com o usuário.

Nesta segunda visualização de exemplo foram suprimidos os Execution Groups que calculam o plano de corte, bem como os que usam esse plano. Por outro lado, foram adicionados dois Execution Groups: um para mostrar o campo escalar em estudo apenas no contorno e um outro para mudar as coordenadas de cada ponto, somando à posição do nó, o deslocamento desse nó multiplicado por um fator gerado com o sequencer, ou seja, um valor entre 0 e 22.


6 - Resultados

Para testar e mostrar o que é possivel ser feito usando-se o DX para visualizar modelos calculados com o ANSYS, foram feitos algumas conversões de modelos compostos por elementos planos e modelos compostos por elementos espaciais. Para cada elemento convertido usou-se o DX na montagem de animações ou detalhes que capazes de enriquecer ainda mais os resultados gráficos conseguidos com o ANSYS. É bom lembrar que não se pode avaliar o output gráfico do ANSYS apenas com as imagens abaixo. Por outro lado, deve-se salientar que para conseguir uma qualidade como a das imagens abaixo, nao é necessário grandes conhecimento nem de ANSYS e nem de DX.


Tabela 1 - Modelos ANSYS (esq.) e Visualizações DX (dir.)




7 - Conclusão

A grande característica do ANSYS2DX é, sem dúvida alguma, a simplicidade da idéia. Um programa para fazer conversões usando arquivos texto, como é o caso desse conversor, pode ser escrito facilmente em qualquer linguagem e não necessariamente em C++. Optou-se por C++ por se tratar apenas do início de um grande projeto. Em etapas posteriores, deverao ser tratados um numero maior dos diversos dados que o ANSYS pode nos dar, e até se possível, o ANSYS2DX deverá ser incrementado para fazer conversões de análises que variem de acordo com o tempo.

O presente trabalho poderá servir de exemplo no desenvolvimento de outros tipos de conversores, que visem integrar o Data Explorer com os mais diversos tipos de softwares de cálculo.


CENAPAD-SP Agosto/1996