Skip to content

Category: português

Uma carreta sobe uma estrada …

Questão: Uma carreta sobe uma estrada cuja inclinação em relação à horizontal é de 30°, a uma velocidade de 40km/h. A força resistiva é igual a 0,75 do peso da carreta. Que velocidade teria a mesma carreta se descesse a estrada com a mesma potência?

Resposta:

Generalizando, vou chamar o ângulo de Θ e o coeficiente da orça resistiva de ψ.

Subida
Figura 1 – A subida

Essa força resistiva não é exatamente o atrito, porque se fosse o atrito teríamos de calcular as componentes do peso para descobrir a normal. O trabalho exercido por essa força resistiva é igual a força ψ·m·g vezes a distância d.

Na subida:
Ea=Eb
onde

  • Ea = m·v²/2 + Em
  • Eb = m·v²/2 + m·g·h + ψ·m·g·d

A carreta ira de um certo ponto A para um certo ponto B com uma mesma velocidade, a inércia pode cuidar disso. Mas a carreta precisa de alguma energia para converter em energia potencial gravitacional e na energia gasta pelo atrito. Essa energia vamos chamar de Em, a energia do motor. A carreta já parte com essa energia guardada para ser transformada em outras formas de energia. Podemos ver isso como o combustível do veículo. Note que nenhuma energia aparece ou se perde.

Igualando as duas equações temos:

  • m·v²/2 + Em = m·v²/2 + m·g·h + ψ·m·g·d

cortando a energia cinética dos dois lados e como h = d·senΘ:

  • Em = m·g·d·senΘ + ψ·m·g·d

colocando d em evidência:

  • Em = d·(m·g·senΘ + ψ·m·g)

A potência do motor na subida é dada pelo trabalho desenvolvido pelo motor dividido pelo tempo levado para subir do ponto A até o ponto B.

  • Pm = Em/t

Como eu não tenho esse tempo eu posso dizer que o tempo é igual à distância dividida pela velocidade.

  • Pm = Em/(d/v)
  • Pm = Em·v/d

Substituindo Em:

  • Pm = d·(m·g·senΘ + ψ·m·g)·v/d
  • Pm = (m·g·senΘ + ψ·m·g)·v
  • Pm = v·m·g·(senΘ + ψ)

Na descida:

Descida
Figura 2 – A descida

Usando o mesmo raciocínio e notação da subida temos:

Ea=Eb
onde

  • Ea = m·v²/2 + ψ·m·g·d
  • Eb = m·v²/2 + m·g·h + Em

igualando as duas equações:

  • m·v²/2 + ψ·m·g·d = m·v²/2 + m·g·h + Em
  • ψ·m·g·d = m·g·h + Em
  • Em = ψ·m·g·d – m·g·h

Como h = d·senΘ:

  • Em = ψ·m·g·d – m·g·d·senΘ
  • Em = d·m·g·(ψ – senΘ)

A potência do motor é dada pelo trabalho sobre o tempo:

  • Pm = Em/t

Novamente não conhecemos o tempo mas sabemos que ele é a distância sobre a velocidade, que vou chamar de v linha para diferenciar da velocidade da carreta na subida:

  • Pm = Em/(d/v’)
  • Pm = Em·v’/d

Substituindo Em:

  • Pm = d·m·g·(ψ – senΘ)·v’/d
  • Pm = v’·m·g·(ψ – senΘ)

Como queremos que a potência na subida seja igual a potência na descida, igualamos as equações das potências:

  • v·m·g·(senΘ + ψ) = v’·m·g·(ψ – senΘ)
  • v·(senΘ + ψ) = v’·(ψ – senΘ)
  • v’·(ψ – senΘ) = v·(senΘ + ψ)
  • v’ = v·(senΘ + ψ) / (ψ – senΘ)

Note que nesse problema, a velocidade na descida só depende da velocidade na subida, o coeficiente da força resistiva e do ângulo Θ.

Calculando para v = 40km/h, ψ = 0,75, Θ = 30º e senΘ = 0,5.

  • v’ = 40km/h·(0,5 + 0,75) / (0,75 – 0,5)
  • v’ = 40km/h·1,25 / 0,25
  • v’ = 200km/h

O Duke é Livre

Duke comendo café com tapioca
Duke comendo um típico café com tapioca. Código-fonte.

Nem todo mundo sabe disso. Quando a Sun fez o anuncio da liberação do Java sobre a GPL eles aproveitaram e também lançaram o Duke em uma licença BSD. As imagens que ilustram esse post foram feitas por mim e incluem seu código-fonte em SVG.

Muitos mascotes de projetos livres não foram lançados sobre a mesma licença do projeto. O antigo demônio do BSD pertence a Marshall K. McKusick. Até mundialmente famoso Tux do Linux parecem pertencer ao seu criador, Larry Ewing. É claro que esses mascotes são usados praticamente livremente embora não tenham sido explicitamente lançados sobre um licença livre.

Duke Estudando e tomando café
Um Duke Acadêmico tomando um café e estudando. Código-fonte.

O Duke além de livre tem um site, (dke.dev.java.net) para reunir desenhos, animações e modelos 3D que qualquer um pode baixar, utilizar e modificar. Há muito material lá.

Duke cangaceiro, tomando um café com tapioca
Duke cangaceiro, comendo tapioca com café. Mais Ceará impossível 🙂 Código-fonte.

Atualizado em 14 de Novembro de 2008:

Um ano da postagem original, olha só o que acharam na praça do Ferreira, centro de Fortaleza:

Soma de dois vetores

Questão 11 do capítulo 2 do livro Física 1, R. Resnick e D. Halliday.

Dois vetores de módulos a e b formam entre si um ângulo ϴ (teta). Determine o módulo s do vetor resultante da soma destes vetores.

Solução:

Podemos desenhar a e b assim, para algum ângulo ϴ qualquer:

Dois vetores a e b com um ângulo teta

A resultante r será algo dessa forma:

Resultante R

Se decompormos b em suas componentes bx e by teremos essa figura:

Vetores completos

Temos aí um triângulo retângulo, onde r é a hipotenusa, by é um cateto e a+bx é o outro cateto. Aplicando pitágoras:

r² = by² + (a+bx)²

Mas sabemos que bx= b·cosϴ e que by= b·senϴ. De forma que podemos escrever e desenvolver

r² = (b·senϴ)² + (a+b·cosϴ)²
r² = b²·sen²ϴ + a²+2·a·b·cosϴ+b²·cos²ϴ
r² = b²·sen²ϴ + a²+2·a·b·cosϴ+b²·cos²ϴ

Colocando b² em evidência.

r² = a² + b²(sen²ϴ+cos²ϴ) + 2·a·b·cosϴ

Da trigonometria sabemos que 1 = sen²ϴ+cos²ϴ.

r² = a² + b² + 2·a·b·cosϴ

Brasão da UFC

Eu já precisei diversas vezes de um brasão da UFC mas sempre fico usando um velho gif de baixa resolução que todo mundo usa.

Quando eu estava refazendo o site da prppg eu comecei a redesenhar vetorialmente o logo da universidade. Como o desenho é vetorial ele pode ser transformado e redimensionado sem restrições de resolução. Ainda não está pronto, faltam as frases em latim, melhorar as folhas de carnaúba e alguns acabamentos. Aqui está uma prévia do trabalho:

Brasão da UFC

O código-fonte está aqui, em SVG, criado no Inkscape. Por razões óbvias eu licencio esse trabalho sob domínio público, mas uma referencia à minha autoria é bem vinda, assim como é bem vinda críticas e melhorias.

Creative Commons License

Brasão da UFC esta licenciado sob a Licença de Domínio Público Creative Commons.

JavaScript: Relógio Digital


Código-Fonte

Aqui na página colocamos:



Que cria um input de texto com nome relógio e depois chamamos o script relogio.js que contém o seguinte código:

function proximo_segundo(){
	var hoje = new Date
	var hora = hoje.getHours()
	var minutos = hoje.getMinutes()
	var segundos = hoje.getSeconds()
	relogio = document.getElementById('relogio')
	relogio.value = hora +":"+minutos+":"+segundos
	setTimeout('proximo_segundo()',1000)
}
proximo_segundo()

Ele cria um objeto Date, encontro o elemento com id ‘relogio’ e coloca no valor dele as informações extraídas do objeto Date. Em seguida ele agenda para daqui a um segundo chamar a si próprio, recursivamente.

Um refinamento que se pode fazer nesse código é uma função auxiliar para preencher com um zero à esquerda, transformando 1:2:3 em 01:02:03. Eu não coloquei isso para deixar o código o mais simples possível.

Como eu ainda sou muito novinho no JavaScript eu não sei se usar uma recursão desse tipo é uma boa idéia ou não. Era isso ou um laço infinito.

Olá Mundo Paralelo com MPI

MPI é a sigla para Message Passing Interface, um padrão de comunicação de dados para computação paralela. O MPI oferece diversas abstracções que facilitam e padronizam o desenvolvimento de aplicações paralelas. Por exemplo, você pode programar para vários processadores, nós de um cluster, supercomputadores ou Internet utilizando a mesma infraestrutura transparentemente.

Supercomputador Nasa
Cluster Columbia da NASA, com 1024 nós.

Como MPI é um padrão, existem vários padrões de implementação, abertas, fechadas, comerciais ou gratuitas. MPI é definido a princípio para C e Fortran, mas há implementações em outras linguagens como Java ou Python, por exemplo. A implementação que eu vou utilizar nesse exemplo é a OpenMPI.

A notícia boa é que você não precisa ter um supercomputador em casa para aprender e praticar computação paralela, uma máquina doméstica serve. Se você tiver uma máquina com múltiplos processadores, melhor ainda.

Instalação

Para instalar um ambiente de desenvolvimento para MPI no Ubuntu Linux basta um comando:

sudo apt-get install build-essential openmpi-dev

Isso vai instalar um conjunto básico de compiladores e o ambiente OpenMPI.

O código

Vamos criar um arquivo chamado ola.c com o conteúdo:

#include
#include
int size, rank;
int main(int argc, char *argv[]){
   MPI_Init(&argc,&argv);
   MPI_Comm_size(MPI_COMM_WORLD,&size);
   MPI_Comm_rank(MPI_COMM_WORLD,&rank);
   printf("Oi. Eu sou o processo %d de %d\n", rank, size);
   MPI_Finalize();
}

Compilação

Para compilar esse código vamos usar o comando mpicc que foi instalado junto com o pacote openmpi-dev. Ele é uma interface para o gcc, e vai cuidar de toda a linkagem com as bibliotecas do MPI. Você pode usar os parâmetros do gcc com o mpicc.

mpicc ola.c -o ola

Se tudo der certo esse comando vai criar o binário ola.

Execução

Outra ferramenta importante é o mpirun, que levantar o mpi nos diversos nós e mandar cada nó executar o binário. O mpirun não precisa de um programa mpi para rodar, por exemplo, se dermos esse comando:

mpirun -np 4 echo oi

Você vai ter essa saída:

oi
oi
oi
oi

Você mandou 4 nós (-np 4) executar o comando echo oi (imprime oi). Para mandar 5 nós executarem nosso binário ola:

mpirun -np 5 ola

E vamos ter uma saída mais ou menos assim:

Oi. Eu sou o processo 1 de 5
Oi. Eu sou o processo 4 de 5
Oi. Eu sou o processo 0 de 5
Oi. Eu sou o processo 2 de 5
Oi. Eu sou o processo 3 de 5

Por que as saídas sairam desordenadas? Porque elas rodaram em paralelo e não temos como saber qual foi sua ordem de execução. Assim cada nó entrou no printf em um momento diferente e imprimiu seu rank e seu size naquele momento. Você pode experimentar usar o parâmetro -np com outros números maiores ou menores que 5.

Troca de Mensagens

Até aqui não há muita graça porque não há troca de mensagens. Há muito o que se dizer sobre como trocar mensagens do MPI mas a maneira mais fácil de se começar é com a função mpi_send.

Vamos fazer um programa bem simples onde o nó 0 vai mandar uma mensagem para o nó 1. A mensagem vai ser um número, 42. Criemos um arquivo chamado msg.c com o código:

#include
#include

int size, rank, msg, source, dest, tag;

int main(int argc, char *argv[]){
   MPI_Status stat;

   MPI_Init(&argc,&argv);
   MPI_Comm_size(MPI_COMM_WORLD,&size);
   MPI_Comm_rank(MPI_COMM_WORLD,&rank);

	if(rank==0){
   	msg = 42; dest = 1; tag = 0;
   	MPI_Send(&msg, 1, MPI_INT, dest, tag, MPI_COMM_WORLD);
   	printf("Processo %d enviou %d para %d.\n", rank, msg, dest);
	}

	if(rank==1){
		source = 0; tag = 0;
		MPI_Recv(&msg, 1, MPI_INT, source, tag, MPI_COMM_WORLD, &stat);
		printf("Processo %d recebeu %d de %d.\n", rank, msg, source);
	}

   MPI_Finalize();
}

No processo de rank 0 vamos enviar o conteúdo da variável inteira msg para o processo de rank 1. Note que no processo de rank 1, o valor de msg não está definido. O comando MPI_Send vai receber 6 parâmetros.

int MPI_Send( void *buf, int count, MPI_Datatype datatype, int dest, int tag, MPI_Comm comm)

  • void *buf, um ponteiro para a mensagem que você vai mandar. No nosso caso a variável inteira msg.
  • int count, a quantidade de elementos que tem nessa mensagem. No nossa caso só 1. Se quisemos mandar um vetor de dois inteiros, seria 2.
  • MPI_Datatype datatype, uma constante que define o tipo de dados que você está enviando. No nosso caso MPI_INT. Isso evita que ajam incompatibilidade no tamanho de inteiros entre arquiteturas diferentes.
  • int dest, o rank do nó destino, o destinatário. No nosso caso o nó 1.
  • int tag, a tag seria num email o assunto da mensagem. Estamos mandando tag 0 então no outro lado tem que estar esperando uma tag 0, caso contrário não há comunicação.
  • MPI_Comm comm, o comunicador. Nesse e na maioria dos casos a constante MPI_COMM_WORLD.

Do outro lado, no processo 1 vamos usar o MPI_recv, que recebe 7 parâmetros.

int MPI_Recv( void *buf, int count, MPI_Datatype datatype, int source, int tag, MPI_Comm comm, MPI_Status *status)

  • void *buf, um ponteiro para onde vai ser guardada a mensagem que vamos receber. No nosso caso a variável msg, que no processo 1 está vazia.
  • int count, a quantidade de elementos que vem nessa mensagem.
  • MPI_Datatype datatype, a mesma constante do MPI_send.
  • int source, o rank do nó remetente. No nosso caso o nó 0.
  • int tag, a tag da mensagem conforme explicado no MPI_send.
  • MPI_Comm comm, o comunicador.
  • MPI_Status *status, uma estrutura para que depois que a função for executada você possa inspecionar detalhes da transmissão. No nosso caso ela é inútil.

Para compilar esse exemplo usamos novamente o mpicc.

mpicc msg.c -o msg

E para executa-lo o mpirun.

mpirun -np 2 msg

O programa vai escrever essa mensagem:

Processo 0 enviou 42 para 1.
Processo 1 recebeu 42 de 0

No processo 1 a msg estava inicialmente vazia e no processo 0 havia 42, mas depois do MPI_recv o processo 1 pode escrever o conteúdo 42 de msg. Logo, houve comunicação.

Dicas

Por um problema no empacotamento do mpich no Ubuntu toda vez que você executa o MPI você recebe umas mensagens horrorosas de erro, que na verdade são só um aviso que ele não encontrou uma placa de rede Infiniband.

Para você silenciar na unha essa chatice use o mpirun assim:

mpiexec –mca btl ^openib -np 1 executável

Onde -np 1 deve ser substituido pelo seu número de processos e executável pelo seu executável.

Outra dica é que você pode utilizar uma distribuição Linux que já venha com o MPI instalado. Por exemplo o Scientific Linux ou o Parallel Knoppix.