I have compared three versions of your query using
- Grails 2.4.4, default settings for caches in a the Grails application
- PostgreSQL 8.4, SQL statement logging has been turned on to count/see the SQL queries.
The first versions one using two calls on the Grails domain class:
def query1() {
  Catalog a = Catalog.findByName('a');
  log.info(a)
  Element b = Element.findByCatalogAndPos(a, 2);
  log.info(b)
  render(b.toString())
}
The 2nd one using criteria
def query2() {
  Element b = Element.createCriteria().get {
    catalog {
      eq("name", "a")
    }
    eq("pos", 2)
  }
  render(b.toString())
}
and the last one using a where query
def query3() {
  def query = Element.where {
    catalog.name == "a" && pos == 2
  }
  Element b = query.get()
  render(b.toString())
}
The first one results in two SQL queries, the other ones will only send one query to the database (using an inner join from Element to Catalog).
As for readability/expressiveness, choose the 3rd version: It expresses your intention in a single line, and it's the most compact version.
As for performance, choose the 2nd or the 3rd version. Under high load, many concurrent users/requests, the number of queries does matter. This might not be an issue for all applications. 
Anway, I'd always choose the 3rd version for the expressiveness; and it will scale, if the query conditions gets more complex over the time.
Update
The SQL statements used by the 1st version:
select this_.id as id1_1_0_, this_.version as version2_1_0_, this_.date_created as date_cre3_1_0_, this_.last_updated as last_upd4_1_0_, this_.name as name5_1_0_, this_.remark as remark6_1_0_ 
  from catalog this_ 
  where this_.name=$1 limit $2
Parameter: $1 = 'a', $2 = '1'
select this_.id as id1_2_0_, this_.version as version2_2_0_, this_.catalog_id as catalog_3_2_0_, this_.date_created as date_cre4_2_0_, this_.last_updated as last_upd5_2_0_, this_.pos as pos6_2_0_, this_.remark as remark7_2_0_ 
  from element this_ 
  where this_.catalog_id=$1 and this_.pos=$2 limit $3
Parameter: $1 = '10', $2 = '2', $3 = '1'
The SQL statement for the 2nd and 3rd version:
select this_.id as id1_2_1_, this_.version as version2_2_1_, this_.catalog_id as catalog_3_2_1_, this_.date_created as date_cre4_2_1_, this_.last_updated as last_upd5_2_1_, this_.pos as pos6_2_1_, this_.remark as remark7_2_1_, catalog_al1_.id as id1_1_0_, catalog_al1_.version as version2_1_0_, catalog_al1_.date_created as date_cre3_1_0_, catalog_al1_.last_updated as last_upd4_1_0_, catalog_al1_.name as name5_1_0_, catalog_al1_.remark as remark6_1_0_ 
  from element this_ inner join catalog catalog_al1_ 
    on this_.catalog_id=catalog_al1_.id 
    where (catalog_al1_.name=$1) and this_.pos=$2
Parameter: $1 = 'a', $2 = '2'